<commit_before>#include "EngineCommand.h"

#include <maya/MArgDatabase.h>
#include <maya/MArgList.h>
#include <maya/MStatus.h>

#include <HAPI/HAPI.h>

#include "SubCommand.h"

#define kLicenseFlag "-lic"
#define kLicenseFlagLong "-license"
#define kHoudiniVersionFlag "-hv"
#define kHoudiniVersionFlagLong "-houdiniVersion"
#define kHoudiniEngineVersionFlag "-hev"
#define kHoudiniEngineVersionFlagLong "-houdiniEngineVersion"
#define kSaveHIPFlag "-sh"
#define kSaveHIPFlagLong "-saveHIP"

const char* EngineCommand::commandName = "houdiniEngine";

class EngineSubCommandLicense : public SubCommand
{
    public:
        virtual MStatus doIt()
        {
            int license;

            HAPI_GetEnvInt(HAPI_ENVINT_LICENSE, &license);

            MString version_string;
            switch(license)
            {
                case HAPI_LICENSE_NONE:
                    version_string = "none";
                    break;
                case HAPI_LICENSE_HOUDINI_ENGINE:
                    version_string = "Houdini-Engine";
                    break;
                case HAPI_LICENSE_HOUDINI:
                    version_string = "Houdini-Escape";
                    break;
                case HAPI_LICENSE_HOUDINI_FX:
                    version_string = "Houdini-Master";
                    break;
                case HAPI_LICENSE_HOUDINI_ENGINE_INDIE:
                    version_string = "Houdini-Engine-Indie";
                    break;
                case HAPI_LICENSE_HOUDINI_INDIE:
                    version_string = "Houdini-Indie";
                    break;
                default:
                    version_string = "Unknown";
                    break;
            }

            MPxCommand::setResult(version_string);

            return MStatus::kSuccess;
        }
};

class EngineSubCommandSaveHIPFile : public SubCommand
{
    public:
        EngineSubCommandSaveHIPFile(const MString &hipFilePath) :
            myHIPFilePath(hipFilePath)
        {
        }

        virtual MStatus doIt()
        {
            HAPI_SaveHIPFile(myHIPFilePath.asChar());

            return MStatus::kSuccess;
        }

    protected:
        MString myHIPFilePath;
};

class EngineSubCommandHoudiniVersion : public SubCommand
{
    public:
        virtual MStatus doIt()
        {
            int major, minor, build;

            HAPI_GetEnvInt(HAPI_ENVINT_VERSION_HOUDINI_MAJOR, &major);
            HAPI_GetEnvInt(HAPI_ENVINT_VERSION_HOUDINI_MINOR, &minor);
            HAPI_GetEnvInt(HAPI_ENVINT_VERSION_HOUDINI_BUILD, &build);

            MString version_string;
            version_string.format(
                    "^1s.^2s.^3s",
                    MString() + major,
                    MString() + minor,
                    MString() + build
                    );

            MPxCommand::setResult(version_string);

            return MStatus::kSuccess;
        }
};

class EngineSubCommandHoudiniEngineVersion : public SubCommand
{
    public:
        virtual MStatus doIt()
        {
            int major, minor, api;

            HAPI_GetEnvInt(HAPI_ENVINT_VERSION_HOUDINI_ENGINE_MAJOR, &major);
            HAPI_GetEnvInt(HAPI_ENVINT_VERSION_HOUDINI_ENGINE_MINOR, &minor);
            HAPI_GetEnvInt(HAPI_ENVINT_VERSION_HOUDINI_ENGINE_API, &api);

            MString version_string;
            version_string.format(
                    "^1s.^2s (API: ^3s)",
                    MString() + major,
                    MString() + minor,
                    MString() + api
                    );

            MPxCommand::setResult(version_string);

            return MStatus::kSuccess;
        }
};

void* EngineCommand::creator()
{
    return new EngineCommand();
}

MSyntax
EngineCommand::newSyntax()
{
    MSyntax syntax;

    // -license returns the Houdini version that's being used.
    CHECK_MSTATUS(syntax.addFlag(kLicenseFlag, kLicenseFlagLong));

    // -houdiniVersion returns the Houdini version that's being used.
    CHECK_MSTATUS(syntax.addFlag(kHoudiniVersionFlag, kHoudiniVersionFlagLong));

    // -houdiniEngineVersion returns the Houdini Engine version that's being
    // used.
    CHECK_MSTATUS(syntax.addFlag(kHoudiniEngineVersionFlag, kHoudiniEngineVersionFlagLong));

    // -saveHIP saves the contents of the current Houdini scene as a hip file
    // expected arguments: hip_file_name - the name of the hip file to save
    CHECK_MSTATUS(syntax.addFlag(kSaveHIPFlag, kSaveHIPFlagLong, MSyntax::kString));

    return syntax;
}

EngineCommand::EngineCommand() :
    mySubCommand(NULL)
{
}

EngineCommand::~EngineCommand()
{
    delete mySubCommand;
}

MStatus
EngineCommand::parseArgs(const MArgList &args)
{
    MStatus status;
    MArgDatabase argData(syntax(), args, &status);
    if(!status)
    {
        return status;
    }

    if(!(
                argData.isFlagSet(kLicenseFlag)
                ^ argData.isFlagSet(kHoudiniVersionFlag)
                ^ argData.isFlagSet(kHoudiniEngineVersionFlag)
                ^ argData.isFlagSet(kSaveHIPFlag)
        ))
    {
        displayError("Exactly one of these flags must be specified:\n"
                kSaveHIPFlagLong "\n"
                );
        return MStatus::kInvalidParameter;
    }

    if(argData.isFlagSet(kLicenseFlag))
    {
        mySubCommand = new EngineSubCommandLicense();
    }

    if(argData.isFlagSet(kHoudiniVersionFlag))
    {
        mySubCommand = new EngineSubCommandHoudiniVersion();
    }

    if(argData.isFlagSet(kHoudiniEngineVersionFlag))
    {
        mySubCommand = new EngineSubCommandHoudiniEngineVersion();
    }

    if(argData.isFlagSet(kSaveHIPFlag))
    {
        MString hipFilePath;
        {
            status = argData.getFlagArgument(kSaveHIPFlag, 0, hipFilePath);
            if(!status)
            {
                displayError("Invalid argument for \"" kSaveHIPFlagLong "\".");
                return status;
            }
        }

        mySubCommand = new EngineSubCommandSaveHIPFile(hipFilePath);
    }

    return MStatus::kSuccess;
}

MStatus EngineCommand::doIt(const MArgList& args)
{
    MStatus status;

    status = parseArgs(args);
    if(!status)
    {
        return status;
    }

    return mySubCommand->doIt();
}

MStatus EngineCommand::redoIt()
{
    return mySubCommand->redoIt();
}

MStatus EngineCommand::undoIt()
{
    return mySubCommand->undoIt();
}

bool EngineCommand::isUndoable() const
{
    return mySubCommand->isUndoable();
}
<commit_msg>Add flags to houdiniEngine command to output the build versions<commit_after>#include "EngineCommand.h"

#include <maya/MArgDatabase.h>
#include <maya/MArgList.h>
#include <maya/MStatus.h>

#include <HAPI/HAPI.h>
#include <HAPI/HAPI_Version.h>

#include "SubCommand.h"

#define kLicenseFlag "-lic"
#define kLicenseFlagLong "-license"
#define kHoudiniVersionFlag "-hv"
#define kHoudiniVersionFlagLong "-houdiniVersion"
#define kHoudiniEngineVersionFlag "-hev"
#define kHoudiniEngineVersionFlagLong "-houdiniEngineVersion"
#define kBuildHoudiniVersionFlag "-bhv"
#define kBuildHoudiniVersionFlagLong "-buildHoudiniVersion"
#define kBuildHoudiniEngineVersionFlag "-bev"
#define kBuildHoudiniEngineVersionFlagLong "-buildHoudiniEngineVersion"
#define kSaveHIPFlag "-sh"
#define kSaveHIPFlagLong "-saveHIP"

const char* EngineCommand::commandName = "houdiniEngine";

class EngineSubCommandLicense : public SubCommand
{
    public:
        virtual MStatus doIt()
        {
            int license;

            HAPI_GetEnvInt(HAPI_ENVINT_LICENSE, &license);

            MString version_string;
            switch(license)
            {
                case HAPI_LICENSE_NONE:
                    version_string = "none";
                    break;
                case HAPI_LICENSE_HOUDINI_ENGINE:
                    version_string = "Houdini-Engine";
                    break;
                case HAPI_LICENSE_HOUDINI:
                    version_string = "Houdini-Escape";
                    break;
                case HAPI_LICENSE_HOUDINI_FX:
                    version_string = "Houdini-Master";
                    break;
                case HAPI_LICENSE_HOUDINI_ENGINE_INDIE:
                    version_string = "Houdini-Engine-Indie";
                    break;
                case HAPI_LICENSE_HOUDINI_INDIE:
                    version_string = "Houdini-Indie";
                    break;
                default:
                    version_string = "Unknown";
                    break;
            }

            MPxCommand::setResult(version_string);

            return MStatus::kSuccess;
        }
};

class EngineSubCommandSaveHIPFile : public SubCommand
{
    public:
        EngineSubCommandSaveHIPFile(const MString &hipFilePath) :
            myHIPFilePath(hipFilePath)
        {
        }

        virtual MStatus doIt()
        {
            HAPI_SaveHIPFile(myHIPFilePath.asChar());

            return MStatus::kSuccess;
        }

    protected:
        MString myHIPFilePath;
};

class EngineSubCommandHoudiniVersion : public SubCommand
{
    public:
        virtual MStatus doIt()
        {
            int major, minor, build;

            HAPI_GetEnvInt(HAPI_ENVINT_VERSION_HOUDINI_MAJOR, &major);
            HAPI_GetEnvInt(HAPI_ENVINT_VERSION_HOUDINI_MINOR, &minor);
            HAPI_GetEnvInt(HAPI_ENVINT_VERSION_HOUDINI_BUILD, &build);

            MString version_string;
            version_string.format(
                    "^1s.^2s.^3s",
                    MString() + major,
                    MString() + minor,
                    MString() + build
                    );

            MPxCommand::setResult(version_string);

            return MStatus::kSuccess;
        }
};

class EngineSubCommandHoudiniEngineVersion : public SubCommand
{
    public:
        virtual MStatus doIt()
        {
            int major, minor, api;

            HAPI_GetEnvInt(HAPI_ENVINT_VERSION_HOUDINI_ENGINE_MAJOR, &major);
            HAPI_GetEnvInt(HAPI_ENVINT_VERSION_HOUDINI_ENGINE_MINOR, &minor);
            HAPI_GetEnvInt(HAPI_ENVINT_VERSION_HOUDINI_ENGINE_API, &api);

            MString version_string;
            version_string.format(
                    "^1s.^2s (API: ^3s)",
                    MString() + major,
                    MString() + minor,
                    MString() + api
                    );

            MPxCommand::setResult(version_string);

            return MStatus::kSuccess;
        }
};

class EngineSubCommandBuildHoudiniVersion : public SubCommand
{
    public:
        virtual MStatus doIt()
        {
            int major = HAPI_VERSION_HOUDINI_MAJOR;
            int minor = HAPI_VERSION_HOUDINI_MINOR;
            int build = HAPI_VERSION_HOUDINI_BUILD;

            MString version_string;
            version_string.format(
                    "^1s.^2s.^3s",
                    MString() + major,
                    MString() + minor,
                    MString() + build
                    );

            MPxCommand::setResult(version_string);

            return MStatus::kSuccess;
        }
};

class EngineSubCommandBuildHoudiniEngineVersion : public SubCommand
{
    public:
        virtual MStatus doIt()
        {
            int major = HAPI_VERSION_HOUDINI_ENGINE_MAJOR;
            int minor = HAPI_VERSION_HOUDINI_ENGINE_MINOR;
            int api = HAPI_VERSION_HOUDINI_ENGINE_API;

            MString version_string;
            version_string.format(
                    "^1s.^2s (API: ^3s)",
                    MString() + major,
                    MString() + minor,
                    MString() + api
                    );

            MPxCommand::setResult(version_string);

            return MStatus::kSuccess;
        }
};

void* EngineCommand::creator()
{
    return new EngineCommand();
}

MSyntax
EngineCommand::newSyntax()
{
    MSyntax syntax;

    // -license returns the Houdini version that's being used.
    CHECK_MSTATUS(syntax.addFlag(kLicenseFlag, kLicenseFlagLong));

    // -houdiniVersion returns the Houdini version that's being used.
    CHECK_MSTATUS(syntax.addFlag(kHoudiniVersionFlag, kHoudiniVersionFlagLong));

    // -houdiniEngineVersion returns the Houdini Engine version that's being
    // used.
    CHECK_MSTATUS(syntax.addFlag(kHoudiniEngineVersionFlag, kHoudiniEngineVersionFlagLong));

    // -buildHoudiniVersion returns the Houdini version that was built with.
    CHECK_MSTATUS(syntax.addFlag(
                kBuildHoudiniVersionFlag,
                kBuildHoudiniVersionFlagLong
                ));

    // -buildHoudiniEngineVersion returns the Houdini Engine version that was
    // built with.
    CHECK_MSTATUS(syntax.addFlag(
                kBuildHoudiniEngineVersionFlag,
                kBuildHoudiniEngineVersionFlagLong
                ));

    // -saveHIP saves the contents of the current Houdini scene as a hip file
    // expected arguments: hip_file_name - the name of the hip file to save
    CHECK_MSTATUS(syntax.addFlag(kSaveHIPFlag, kSaveHIPFlagLong, MSyntax::kString));

    return syntax;
}

EngineCommand::EngineCommand() :
    mySubCommand(NULL)
{
}

EngineCommand::~EngineCommand()
{
    delete mySubCommand;
}

MStatus
EngineCommand::parseArgs(const MArgList &args)
{
    MStatus status;
    MArgDatabase argData(syntax(), args, &status);
    if(!status)
    {
        return status;
    }

    if(!(
                argData.isFlagSet(kLicenseFlag)
                ^ argData.isFlagSet(kHoudiniVersionFlag)
                ^ argData.isFlagSet(kHoudiniEngineVersionFlag)
                ^ argData.isFlagSet(kBuildHoudiniVersionFlag)
                ^ argData.isFlagSet(kBuildHoudiniEngineVersionFlag)
                ^ argData.isFlagSet(kSaveHIPFlag)
        ))
    {
        displayError("Exactly one of these flags must be specified:\n"
                kSaveHIPFlagLong "\n"
                );
        return MStatus::kInvalidParameter;
    }

    if(argData.isFlagSet(kLicenseFlag))
    {
        mySubCommand = new EngineSubCommandLicense();
    }

    if(argData.isFlagSet(kHoudiniVersionFlag))
    {
        mySubCommand = new EngineSubCommandHoudiniVersion();
    }

    if(argData.isFlagSet(kHoudiniEngineVersionFlag))
    {
        mySubCommand = new EngineSubCommandHoudiniEngineVersion();
    }

    if(argData.isFlagSet(kBuildHoudiniVersionFlag))
    {
        mySubCommand = new EngineSubCommandBuildHoudiniVersion();
    }

    if(argData.isFlagSet(kBuildHoudiniEngineVersionFlag))
    {
        mySubCommand = new EngineSubCommandBuildHoudiniEngineVersion();
    }

    if(argData.isFlagSet(kSaveHIPFlag))
    {
        MString hipFilePath;
        {
            status = argData.getFlagArgument(kSaveHIPFlag, 0, hipFilePath);
            if(!status)
            {
                displayError("Invalid argument for \"" kSaveHIPFlagLong "\".");
                return status;
            }
        }

        mySubCommand = new EngineSubCommandSaveHIPFile(hipFilePath);
    }

    return MStatus::kSuccess;
}

MStatus EngineCommand::doIt(const MArgList& args)
{
    MStatus status;

    status = parseArgs(args);
    if(!status)
    {
        return status;
    }

    return mySubCommand->doIt();
}

MStatus EngineCommand::redoIt()
{
    return mySubCommand->redoIt();
}

MStatus EngineCommand::undoIt()
{
    return mySubCommand->undoIt();
}

bool EngineCommand::isUndoable() const
{
    return mySubCommand->isUndoable();
}
<|endoftext|>


<commit_before>/* bzflag
 * Copyright (c) 1993 - 2005 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 LICENSE 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.
 */

// Provide BZFS with a list server connection

/* class header */
#include "ListServerConnection.h"

/* system implementation headers */
#include <string.h>
#include <string>
#include <math.h>
#include <errno.h>

/* common implementation headers */
#include "bzfio.h"
#include "version.h"
#include "TextUtils.h"
#include "Protocol.h"
#include "GameKeeper.h"

/* local implementation headers */
#include "CmdLineOptions.h"

// FIXME remove externs!
extern PingPacket getTeamCounts();
extern uint16_t curMaxPlayers;
extern void sendMessage(int playerIndex, PlayerId targetPlayer, const char *message);
extern void sendPlayerInfo(void);
extern void sendIPUpdate(int targetPlayer, int playerIndex);
extern CmdLineOptions *clOptions;

const int ListServerLink::NotConnected = -1;

ListServerLink::ListServerLink(std::string listServerURL, std::string publicizedAddress, std::string publicizedTitle)
{
  // parse url
  std::string protocol, _hostname, _pathname;
  int _port = 80;
  bool useDefault = false;

  // use default if it can't be parsed
  if (!BzfNetwork::parseURL(listServerURL, protocol, _hostname, _port,
			    _pathname))
    useDefault = true;

  // use default if wrong protocol or invalid port
  if ((protocol != "http") || (_port < 1) || (_port > 65535))
    useDefault = true;

  // use default if bad address
  Address _address = Address::getHostAddress(_hostname);
  if (_address.isAny())
    useDefault = true;

  // parse default list server URL if we need to; assume default works
  if (useDefault) {
    BzfNetwork::parseURL(DefaultListServerURL, protocol, _hostname, _port,
			 _pathname);
    DEBUG1("Provided list server URL (%s) is invalid.  Using default of %s.\n", listServerURL.c_str(), DefaultListServerURL);
  }

  // add to list
  address          = _address;
  port             = _port;
  pathname         = _pathname;
  hostname         = _hostname;
  this->linkSocket = NotConnected;

  if (clOptions->pingInterface != "")
    this->localAddress	     = Address::getHostAddress(clOptions->pingInterface);
  this->publicizeAddress     = publicizedAddress;
  this->publicizeDescription = publicizedTitle;
  this->publicizeServer	     = true;  //if this c'tor is called, it's safe to publicize

  // schedule initial ADD message
  queueMessage(ListServerLink::ADD);
}

ListServerLink::ListServerLink()
{
  // does not create a usable link, so checks should be placed
  // in  all public member functions to ensure that nothing tries
  // to happen if publicizeServer is false
  this->linkSocket = NotConnected;
  this->publicizeServer = false;
}

ListServerLink::~ListServerLink()
{
  // now tell the list server that we're going away.  this can
  // take some time but we don't want to wait too long.  we do
  // our own multiplexing loop and wait for a maximum of 3 seconds
  // total.

  // if we aren't supposed to be publicizing, skip the whole thing
  // and don't waste 3 seconds.
  if (!publicizeServer)
    return;

  queueMessage(ListServerLink::REMOVE);
  TimeKeeper start = TimeKeeper::getCurrent();
  do {
    // compute timeout
    float waitTime = float(3.0 - (TimeKeeper::getCurrent() - start));
    if (waitTime <= 0.0f)
      break;
    if (!isConnected()) //queueMessage should have connected us
      break;
    // check for list server socket connection
    int fdMax = -1;
    fd_set write_set;
    fd_set read_set;
    FD_ZERO(&write_set);
    FD_ZERO(&read_set);
    if (phase == ListServerLink::CONNECTING) {
      FD_SET((unsigned int)linkSocket, &write_set);
    } else {
      FD_SET((unsigned int)linkSocket, &read_set);
    }
    fdMax = linkSocket;

    // wait for socket to connect or timeout
    struct timeval timeout;
    timeout.tv_sec = long(floorf(waitTime));
    timeout.tv_usec = long(1.0e+6f * (waitTime - floorf(waitTime)));
    int nfound = select(fdMax + 1, (fd_set*)&read_set, (fd_set*)&write_set,
			0, &timeout);
    if (nfound == 0)
      // Time has gone, close and go
      break;
    // check for connection to list server
    if (FD_ISSET(linkSocket, &write_set))
      sendQueuedMessages();
    else if (FD_ISSET(linkSocket, &read_set))
      read();
  } while (true);

  // stop list server communication
  closeLink();
}

void ListServerLink::closeLink()
{
  if (isConnected()) {
    close(linkSocket);
    DEBUG4("Closing List Server\n");
    linkSocket = NotConnected;
  }
}

void ListServerLink::read()
{
  if (isConnected()) {
    char buf[2048];
    int bytes = recv(linkSocket, buf, sizeof(buf)-1, 0);
    // TODO don't close unless we've got it all
    closeLink();
    buf[bytes]=0;
    char* base = buf;
    static char *tokGoodIdentifier = "TOKGOOD: ";
    static char *tokBadIdentifier = "TOKBAD: ";
    // walks entire reply including HTTP headers
    while (*base) {
      // find next newline
      char* scan = base;
      while (*scan && *scan != '\r' && *scan != '\n') scan++;
      // if no newline then no more complete replies
      if (*scan != '\r' && *scan != '\n') break;
      while (*scan && (*scan == '\r' || *scan == '\n')) *scan++ = '\0';
      DEBUG4("Got line: \"%s\"\n", base);
      // TODO don't do this if we don't want central logins
      if (strncmp(base, tokGoodIdentifier, strlen(tokGoodIdentifier)) == 0) {
	char *callsign, *group;
	callsign = base + strlen(tokGoodIdentifier);
	DEBUG3("Got: %s\n", base);
	group = callsign;
	while (*group && (*group != ':')) group++;
	while (*group && (*group == ':')) *group++ = 0;
	int playerIndex = GameKeeper::Player::getPlayerIDByName(callsign);
	if (playerIndex < curMaxPlayers) {
	  GameKeeper::Player *playerData = GameKeeper::Player::getPlayerByIndex(playerIndex);
	  if (playerData != NULL) {
	    // don't accept the global auth if there's a local account of the same name
	    // and the local account is not marked as being the same as the global account
	    if (!playerData->accessInfo.hasRealPassword()
		|| playerData->accessInfo.getUserInfo(callsign).hasGroup("LOCAL.GLOBAL")) {
	      if (!playerData->accessInfo.isRegistered())
		playerData->accessInfo.storeInfo(NULL);
	      playerData->accessInfo.setPermissionRights();
	      while (*group) {
		char *nextgroup = group;
		while (*nextgroup && (*nextgroup != ':')) nextgroup++;
		while (*nextgroup && (*nextgroup == ':')) *nextgroup++ = 0;
		playerData->accessInfo.addGroup(group);
		//DEBUG3("Got: [%d] \"%s\" \"%s\"\n", playerIndex, callsign, group);
		group = nextgroup;
	      }
		  playerData->authentication.global(true);
	      sendMessage(ServerPlayer, playerIndex, "Global login approved!");
	      sendIPUpdate(playerIndex, -1);
	      sendPlayerInfo();
	    } else {
	      sendMessage(ServerPlayer, playerIndex, "Global login rejected. "
			  "This callsign is registered locally on this server.");
	      sendMessage(ServerPlayer, playerIndex, "If the local account is yours, "
			  "/identify, /deregister and reconnnect, "
			  "or ask an admin for the LOCAL.GLOBAL group.");
	      sendMessage(ServerPlayer, playerIndex, "If it is not yours, please ask an admin "
			  "to deregister it so that you may use your global callsign.");
	    }
	    playerData->setNeedThisHostbanChecked(true);
	    playerData->player.clearToken();
	  }
	}
      } else if (strncmp(base, tokBadIdentifier, strlen(tokBadIdentifier)) == 0) {
	char *callsign;
	callsign = base + strlen(tokBadIdentifier);
	int playerIndex = GameKeeper::Player::getPlayerIDByName(callsign);
	DEBUG3("Got: [%d] %s\n", playerIndex, base);
	if (playerIndex < curMaxPlayers) {
	  GameKeeper::Player *playerData = GameKeeper::Player::getPlayerByIndex(playerIndex);
	  sendMessage(ServerPlayer, playerIndex, "Global login rejected, bad token.");
	  if (playerData != NULL) {
	    playerData->setNeedThisHostbanChecked(true);
	    playerData->player.clearToken();
	  }
	}
      }

      // next reply
      base = scan;
    }
    if (nextMessageType != ListServerLink::NONE) {
      // There was a pending request arrived after we write:
      // we should redo all the stuff
      openLink();
    }
  }
}

void ListServerLink::openLink()
{
  // start opening connection if not already doing so
  if (!isConnected()) {
    linkSocket = socket(AF_INET, SOCK_STREAM, 0);
    DEBUG4("Opening List Server\n");
    if (!isConnected()) {
      return;
    }

    // set to non-blocking for connect
    if (BzfNetwork::setNonBlocking(linkSocket) < 0) {
      closeLink();
      return;
    }

    // Make our connection come from our serverAddress in case we have
    // multiple/masked IPs so the list server can verify us.
    struct sockaddr_in addr;
    memset(&addr, 0, sizeof(addr));
    addr.sin_family = AF_INET;
    addr.sin_addr = localAddress;

    // assign the address to the socket
    if (bind(linkSocket, (CNCTType*)&addr, sizeof(addr)) < 0) {
      closeLink();
      return;
    }

    // connect.  this should fail with EINPROGRESS but check for
    // success just in case.
    memset(&addr, 0, sizeof(addr));
    addr.sin_family = AF_INET;
    addr.sin_port   = htons(port);
    addr.sin_addr   = address;
    if (connect(linkSocket, (CNCTType*)&addr, sizeof(addr)) < 0) {
#if defined(_WIN32)
#undef EINPROGRESS
#define EINPROGRESS EWOULDBLOCK
#endif
      if (getErrno() != EINPROGRESS) {
	nerror("connecting to list server");
	// try to lookup dns name again in case it moved
	this->address = Address::getHostAddress(this->hostname);
	closeLink();
      } else {
	phase = CONNECTING;
      }
    } else {
      // shouldn't arrive here. Just in case, clean
      DEBUG3("list server connect and close?\n");
      closeLink();
    }
  }
}

void ListServerLink::queueMessage(MessageType type)
{
  // ignore if the server is not public
  if (!publicizeServer) return;

  // Open network connection only if closed
  if (!isConnected()) openLink();

  // record next message to send.
  nextMessageType = type;
}

void ListServerLink::sendQueuedMessages()
{
  if (!isConnected())
    return;

  if (nextMessageType == ListServerLink::ADD) {
    DEBUG3("Queuing ADD message to list server\n");
    addMe(getTeamCounts(), publicizeAddress, TextUtils::url_encode(publicizeDescription));
    lastAddTime = TimeKeeper::getCurrent();
  } else if (nextMessageType == ListServerLink::REMOVE) {
    DEBUG3("Queuing REMOVE message to list server\n");
    removeMe(publicizeAddress);
  }
}

void ListServerLink::addMe(PingPacket pingInfo,
			   std::string publicizedAddress,
			   std::string publicizedTitle)
{
  std::string msg;

  // encode ping reply as ascii hex digits plus NULL
  char gameInfo[PingPacketHexPackedSize + 1];
  pingInfo.packHex(gameInfo);

  // TODO we probably should convert to a POST. List server now allows either
  // send ADD message (must send blank line)
  msg = TextUtils::format("GET %s?action=ADD&nameport=%s&version=%s&gameinfo=%s&build=%s",
    pathname.c_str(), publicizedAddress.c_str(),
    getServerVersion(), gameInfo,
    getAppVersion());
  msg += "&checktokens=";
  // callsign1@ip1=token1%0D%0Acallsign2@ip2=token2%0D%0A
  for (int i = 0; i < curMaxPlayers; i++) {
    GameKeeper::Player *playerData = GameKeeper::Player::getPlayerByIndex(i);
    if (!playerData)
      continue;
    NetHandler *handler = playerData->netHandler;
    std::string encodedCallsign = TextUtils::url_encode(playerData->player.getCallSign());
    if (strlen(playerData->player.getCallSign()) && strlen(playerData->player.getToken())) {
      msg += encodedCallsign;
      Address addr = handler->getIPAddress();
      if (!addr.isPrivate()) {
	msg += "@";
	msg += handler->getTargetIP();
      }
      msg += "=";
      msg += playerData->player.getToken();
      msg += "%0D%0A";
    }
  }
  // *groups=GROUP0%0D%0AGROUP1%0D%0A
  msg += "&groups=";
  PlayerAccessMap::iterator itr = groupAccess.begin();
  for ( ; itr != groupAccess.end(); itr++) {
    if (itr->first.substr(0, 6) != "LOCAL.") {
      msg += itr->first.c_str();
      msg += "%0D%0A";
    }
  }

  msg += TextUtils::format("&title=%s HTTP/1.1\r\n"
      "User-Agent: bzfs %s\r\n"
      "Host: %s\r\n"
      "Cache-Control: no-cache\r\n"
      "Connection: close\r\n"
      "\r\n",
    publicizedTitle.c_str(),
    getAppVersion(),
    hostname.c_str());
  sendLSMessage(msg);
}

void ListServerLink::removeMe(std::string publicizedAddress)
{
  std::string msg;
  // send REMOVE (must send blank line)
  msg = TextUtils::format("GET %s?action=REMOVE&nameport=%s HTTP/1.1\r\n"
    "User-Agent: bzfs %s\r\n"
    "Host: %s\r\n"
    "Cache-Control: no-cache\r\n"
    "Connection: close\r\n"
    "\r\n",
    pathname.c_str(),
    publicizedAddress.c_str(),
    getAppVersion(),
    hostname.c_str());
  sendLSMessage(msg);
}

void ListServerLink::sendLSMessage(std::string message)
{
  const int bufsize = 4096;
  char msg[bufsize];
  strncpy(msg, message.c_str(), bufsize);
  msg[bufsize - 1] = 0;
  if (strlen(msg) > 0) {
    DEBUG3("%s\n", msg);
    if (send(linkSocket, msg, strlen(msg), 0) == -1) {
      perror("List server send failed");
      DEBUG3("Unable to send to the list server!\n");
      closeLink();
    } else {
      nextMessageType = ListServerLink::NONE;
      phase	   = ListServerLink::WRITTEN;
    }
  } else {
    closeLink();
  }
}

// Local Variables: ***
// mode:C++ ***
// tab-width: 8 ***
// c-basic-offset: 2 ***
// indent-tabs-mode: t ***
// End: ***
// ex: shiftwidth=2 tabstop=8
<commit_msg>Change list server request methods from 'GET' to 'POST (libcurl NOT used).<commit_after>/* bzflag
 * Copyright (c) 1993 - 2005 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 LICENSE 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.
 */

// Provide BZFS with a list server connection

/* class header */
#include "ListServerConnection.h"

/* system implementation headers */
#include <string.h>
#include <string>
#include <math.h>
#include <errno.h>

/* common implementation headers */
#include "bzfio.h"
#include "version.h"
#include "TextUtils.h"
#include "Protocol.h"
#include "GameKeeper.h"

/* local implementation headers */
#include "CmdLineOptions.h"

// FIXME remove externs!
extern PingPacket getTeamCounts();
extern uint16_t curMaxPlayers;
extern void sendMessage(int playerIndex, PlayerId targetPlayer, const char *message);
extern void sendPlayerInfo(void);
extern void sendIPUpdate(int targetPlayer, int playerIndex);
extern CmdLineOptions *clOptions;

const int ListServerLink::NotConnected = -1;

ListServerLink::ListServerLink(std::string listServerURL, std::string publicizedAddress, std::string publicizedTitle)
{
  // parse url
  std::string protocol, _hostname, _pathname;
  int _port = 80;
  bool useDefault = false;

  // use default if it can't be parsed
  if (!BzfNetwork::parseURL(listServerURL, protocol, _hostname, _port,
			    _pathname))
    useDefault = true;

  // use default if wrong protocol or invalid port
  if ((protocol != "http") || (_port < 1) || (_port > 65535))
    useDefault = true;

  // use default if bad address
  Address _address = Address::getHostAddress(_hostname);
  if (_address.isAny())
    useDefault = true;

  // parse default list server URL if we need to; assume default works
  if (useDefault) {
    BzfNetwork::parseURL(DefaultListServerURL, protocol, _hostname, _port,
			 _pathname);
    DEBUG1("Provided list server URL (%s) is invalid.  Using default of %s.\n", listServerURL.c_str(), DefaultListServerURL);
  }

  // add to list
  address          = _address;
  port             = _port;
  pathname         = _pathname;
  hostname         = _hostname;
  this->linkSocket = NotConnected;

  if (clOptions->pingInterface != "")
    this->localAddress	     = Address::getHostAddress(clOptions->pingInterface);
  this->publicizeAddress     = publicizedAddress;
  this->publicizeDescription = publicizedTitle;
  this->publicizeServer	     = true;  //if this c'tor is called, it's safe to publicize

  // schedule initial ADD message
  queueMessage(ListServerLink::ADD);
}

ListServerLink::ListServerLink()
{
  // does not create a usable link, so checks should be placed
  // in  all public member functions to ensure that nothing tries
  // to happen if publicizeServer is false
  this->linkSocket = NotConnected;
  this->publicizeServer = false;
}

ListServerLink::~ListServerLink()
{
  // now tell the list server that we're going away.  this can
  // take some time but we don't want to wait too long.  we do
  // our own multiplexing loop and wait for a maximum of 3 seconds
  // total.

  // if we aren't supposed to be publicizing, skip the whole thing
  // and don't waste 3 seconds.
  if (!publicizeServer)
    return;

  queueMessage(ListServerLink::REMOVE);
  TimeKeeper start = TimeKeeper::getCurrent();
  do {
    // compute timeout
    float waitTime = float(3.0 - (TimeKeeper::getCurrent() - start));
    if (waitTime <= 0.0f)
      break;
    if (!isConnected()) //queueMessage should have connected us
      break;
    // check for list server socket connection
    int fdMax = -1;
    fd_set write_set;
    fd_set read_set;
    FD_ZERO(&write_set);
    FD_ZERO(&read_set);
    if (phase == ListServerLink::CONNECTING) {
      FD_SET((unsigned int)linkSocket, &write_set);
    } else {
      FD_SET((unsigned int)linkSocket, &read_set);
    }
    fdMax = linkSocket;

    // wait for socket to connect or timeout
    struct timeval timeout;
    timeout.tv_sec = long(floorf(waitTime));
    timeout.tv_usec = long(1.0e+6f * (waitTime - floorf(waitTime)));
    int nfound = select(fdMax + 1, (fd_set*)&read_set, (fd_set*)&write_set,
			0, &timeout);
    if (nfound == 0)
      // Time has gone, close and go
      break;
    // check for connection to list server
    if (FD_ISSET(linkSocket, &write_set))
      sendQueuedMessages();
    else if (FD_ISSET(linkSocket, &read_set))
      read();
  } while (true);

  // stop list server communication
  closeLink();
}

void ListServerLink::closeLink()
{
  if (isConnected()) {
    close(linkSocket);
    DEBUG4("Closing List Server\n");
    linkSocket = NotConnected;
  }
}

void ListServerLink::read()
{
  if (isConnected()) {
    char buf[2048];
    int bytes = recv(linkSocket, buf, sizeof(buf)-1, 0);
    // TODO don't close unless we've got it all
    closeLink();
    buf[bytes]=0;
    char* base = buf;
    static char *tokGoodIdentifier = "TOKGOOD: ";
    static char *tokBadIdentifier = "TOKBAD: ";
    // walks entire reply including HTTP headers
    while (*base) {
      // find next newline
      char* scan = base;
      while (*scan && *scan != '\r' && *scan != '\n') scan++;
      // if no newline then no more complete replies
      if (*scan != '\r' && *scan != '\n') break;
      while (*scan && (*scan == '\r' || *scan == '\n')) *scan++ = '\0';
      DEBUG4("Got line: \"%s\"\n", base);
      // TODO don't do this if we don't want central logins
      if (strncmp(base, tokGoodIdentifier, strlen(tokGoodIdentifier)) == 0) {
	char *callsign, *group;
	callsign = base + strlen(tokGoodIdentifier);
	DEBUG3("Got: %s\n", base);
	group = callsign;
	while (*group && (*group != ':')) group++;
	while (*group && (*group == ':')) *group++ = 0;
	int playerIndex = GameKeeper::Player::getPlayerIDByName(callsign);
	if (playerIndex < curMaxPlayers) {
	  GameKeeper::Player *playerData = GameKeeper::Player::getPlayerByIndex(playerIndex);
	  if (playerData != NULL) {
	    // don't accept the global auth if there's a local account of the same name
	    // and the local account is not marked as being the same as the global account
	    if (!playerData->accessInfo.hasRealPassword()
		|| playerData->accessInfo.getUserInfo(callsign).hasGroup("LOCAL.GLOBAL")) {
	      if (!playerData->accessInfo.isRegistered())
		playerData->accessInfo.storeInfo(NULL);
	      playerData->accessInfo.setPermissionRights();
	      while (*group) {
		char *nextgroup = group;
		while (*nextgroup && (*nextgroup != ':')) nextgroup++;
		while (*nextgroup && (*nextgroup == ':')) *nextgroup++ = 0;
		playerData->accessInfo.addGroup(group);
		//DEBUG3("Got: [%d] \"%s\" \"%s\"\n", playerIndex, callsign, group);
		group = nextgroup;
	      }
		  playerData->authentication.global(true);
	      sendMessage(ServerPlayer, playerIndex, "Global login approved!");
	      sendIPUpdate(playerIndex, -1);
	      sendPlayerInfo();
	    } else {
	      sendMessage(ServerPlayer, playerIndex, "Global login rejected. "
			  "This callsign is registered locally on this server.");
	      sendMessage(ServerPlayer, playerIndex, "If the local account is yours, "
			  "/identify, /deregister and reconnnect, "
			  "or ask an admin for the LOCAL.GLOBAL group.");
	      sendMessage(ServerPlayer, playerIndex, "If it is not yours, please ask an admin "
			  "to deregister it so that you may use your global callsign.");
	    }
	    playerData->setNeedThisHostbanChecked(true);
	    playerData->player.clearToken();
	  }
	}
      } else if (strncmp(base, tokBadIdentifier, strlen(tokBadIdentifier)) == 0) {
	char *callsign;
	callsign = base + strlen(tokBadIdentifier);
	int playerIndex = GameKeeper::Player::getPlayerIDByName(callsign);
	DEBUG3("Got: [%d] %s\n", playerIndex, base);
	if (playerIndex < curMaxPlayers) {
	  GameKeeper::Player *playerData = GameKeeper::Player::getPlayerByIndex(playerIndex);
	  sendMessage(ServerPlayer, playerIndex, "Global login rejected, bad token.");
	  if (playerData != NULL) {
	    playerData->setNeedThisHostbanChecked(true);
	    playerData->player.clearToken();
	  }
	}
      }

      // next reply
      base = scan;
    }
    if (nextMessageType != ListServerLink::NONE) {
      // There was a pending request arrived after we write:
      // we should redo all the stuff
      openLink();
    }
  }
}

void ListServerLink::openLink()
{
  // start opening connection if not already doing so
  if (!isConnected()) {
    linkSocket = socket(AF_INET, SOCK_STREAM, 0);
    DEBUG4("Opening List Server\n");
    if (!isConnected()) {
      return;
    }

    // set to non-blocking for connect
    if (BzfNetwork::setNonBlocking(linkSocket) < 0) {
      closeLink();
      return;
    }

    // Make our connection come from our serverAddress in case we have
    // multiple/masked IPs so the list server can verify us.
    struct sockaddr_in addr;
    memset(&addr, 0, sizeof(addr));
    addr.sin_family = AF_INET;
    addr.sin_addr = localAddress;

    // assign the address to the socket
    if (bind(linkSocket, (CNCTType*)&addr, sizeof(addr)) < 0) {
      closeLink();
      return;
    }

    // connect.  this should fail with EINPROGRESS but check for
    // success just in case.
    memset(&addr, 0, sizeof(addr));
    addr.sin_family = AF_INET;
    addr.sin_port   = htons(port);
    addr.sin_addr   = address;
    if (connect(linkSocket, (CNCTType*)&addr, sizeof(addr)) < 0) {
#if defined(_WIN32)
#undef EINPROGRESS
#define EINPROGRESS EWOULDBLOCK
#endif
      if (getErrno() != EINPROGRESS) {
	nerror("connecting to list server");
	// try to lookup dns name again in case it moved
	this->address = Address::getHostAddress(this->hostname);
	closeLink();
      } else {
	phase = CONNECTING;
      }
    } else {
      // shouldn't arrive here. Just in case, clean
      DEBUG3("list server connect and close?\n");
      closeLink();
    }
  }
}

void ListServerLink::queueMessage(MessageType type)
{
  // ignore if the server is not public
  if (!publicizeServer) return;

  // Open network connection only if closed
  if (!isConnected()) openLink();

  // record next message to send.
  nextMessageType = type;
}

void ListServerLink::sendQueuedMessages()
{
  if (!isConnected())
    return;

  if (nextMessageType == ListServerLink::ADD) {
    DEBUG3("Queuing ADD message to list server\n");
    addMe(getTeamCounts(), publicizeAddress, TextUtils::url_encode(publicizeDescription));
    lastAddTime = TimeKeeper::getCurrent();
  } else if (nextMessageType == ListServerLink::REMOVE) {
    DEBUG3("Queuing REMOVE message to list server\n");
    removeMe(publicizeAddress);
  }
}

void ListServerLink::addMe(PingPacket pingInfo,
			   std::string publicizedAddress,
			   std::string publicizedTitle)
{
  std::string msg;

  // encode ping reply as ascii hex digits plus NULL
  char gameInfo[PingPacketHexPackedSize + 1];
  pingInfo.packHex(gameInfo);

  // TODO we probably should convert to a POST. List server now allows either
  // send ADD message (must send blank line)
  msg = TextUtils::format("POST %s?action=ADD&nameport=%s&version=%s&gameinfo=%s&build=%s",
    pathname.c_str(), publicizedAddress.c_str(),
    getServerVersion(), gameInfo,
    getAppVersion());
  msg += "&checktokens=";
  // callsign1@ip1=token1%0D%0Acallsign2@ip2=token2%0D%0A
  for (int i = 0; i < curMaxPlayers; i++) {
    GameKeeper::Player *playerData = GameKeeper::Player::getPlayerByIndex(i);
    if (!playerData)
      continue;
    NetHandler *handler = playerData->netHandler;
    std::string encodedCallsign = TextUtils::url_encode(playerData->player.getCallSign());
    if (strlen(playerData->player.getCallSign()) && strlen(playerData->player.getToken())) {
      msg += encodedCallsign;
      Address addr = handler->getIPAddress();
      if (!addr.isPrivate()) {
	msg += "@";
	msg += handler->getTargetIP();
      }
      msg += "=";
      msg += playerData->player.getToken();
      msg += "%0D%0A";
    }
  }
  // *groups=GROUP0%0D%0AGROUP1%0D%0A
  msg += "&groups=";
  PlayerAccessMap::iterator itr = groupAccess.begin();
  for ( ; itr != groupAccess.end(); itr++) {
    if (itr->first.substr(0, 6) != "LOCAL.") {
      msg += itr->first.c_str();
      msg += "%0D%0A";
    }
  }

  msg += TextUtils::format("&title=%s HTTP/1.1\r\n"
      "User-Agent: bzfs %s\r\n"
      "Host: %s\r\n"
      "Cache-Control: no-cache\r\n"
      "Connection: close\r\n"
      "\r\n",
    publicizedTitle.c_str(),
    getAppVersion(),
    hostname.c_str());
  sendLSMessage(msg);
}

void ListServerLink::removeMe(std::string publicizedAddress)
{
  std::string msg;
  // send REMOVE (must send blank line)
  msg = TextUtils::format("POST %s?action=REMOVE&nameport=%s HTTP/1.1\r\n"
    "User-Agent: bzfs %s\r\n"
    "Host: %s\r\n"
    "Cache-Control: no-cache\r\n"
    "Connection: close\r\n"
    "\r\n",
    pathname.c_str(),
    publicizedAddress.c_str(),
    getAppVersion(),
    hostname.c_str());
  sendLSMessage(msg);
}

void ListServerLink::sendLSMessage(std::string message)
{
  const int bufsize = 4096;
  char msg[bufsize];
  strncpy(msg, message.c_str(), bufsize);
  msg[bufsize - 1] = 0;
  if (strlen(msg) > 0) {
    DEBUG3("%s\n", msg);
    if (send(linkSocket, msg, strlen(msg), 0) == -1) {
      perror("List server send failed");
      DEBUG3("Unable to send to the list server!\n");
      closeLink();
    } else {
      nextMessageType = ListServerLink::NONE;
      phase	   = ListServerLink::WRITTEN;
    }
  } else {
    closeLink();
  }
}

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


<commit_before>// StdLib.cpp
// This file is part of the EScript programming language.
// See copyright notice in EScript.h
// ------------------------------------------------------
#include "StdLib.h"

#include "../EScript/EScript.h"
#include "../EScript/Parser/Compiler.h"
#include "../EScript/Parser/Parser.h"
#include "../EScript/Utils/IO/IO.h"
#include "ext/JSON.h"

#include <sstream>
#include <stdlib.h>
#include <ctime>
#include <unistd.h>

#if defined(_WIN32)
#include <windows.h>
#endif

namespace EScript{

std::string StdLib::getOS(){
	#if defined(_WIN32) || defined(_WIN64)
	return std::string("WINDOWS");
	#elif defined(__APPLE__)
	return std::string("MAC OS");
	#elif defined(__linux__)
	return std::string("LINUX");
	#elif defined(__unix__)
	return std::string("UNIX");
	#else
	return std::string("UNKNOWN");
	#endif
}

//! (static)
void StdLib::print_r(Object * o,int maxLevel,int level) {
	if (!o) return;
	if (level>maxLevel) {
		std::cout << " ... \n";
		return;
	}

	if (Array * a=dynamic_cast<Array *>(o)) {
		std::cout << "[\n";
		ERef<Iterator> itRef=a->getIterator();
		int nr=0;
		while (!itRef->end()) {
			ObjRef valueRef=itRef->value();
			ObjRef keyRef=itRef->key();
			if (nr++>0)std::cout << ",\n";
			if (!valueRef.isNull()) {
				for (int i=0;i<level;i++)
					std::cout << "\t";
				std::cout << "["<<keyRef.toString() <<"] : ";
				print_r(valueRef.get(),maxLevel,level+1);

			}
			itRef->next();
		}
		std::cout << "\n";
		for (int i=0;i<level-1;i++)
			std::cout << "\t";
		std::cout << "]";
	} else if (Map * m=dynamic_cast<Map *>(o)) {
		std::cout << "{\n";
		ERef<Iterator> itRef=m->getIterator();
		int nr=0;
		while (!itRef->end()) {
			ObjRef valueRef=itRef->value();
			ObjRef keyRef=itRef->key();
			if (nr++>0)
				std::cout << ",\n";
			if (!valueRef.isNull()) {
				for (int i=0;i<level;i++)
					std::cout << "\t";
				std::cout << "["<<keyRef.toString() <<"] : ";
				print_r(valueRef.get(),maxLevel,level+1);

			}

			itRef->next();
		}
		std::cout << "\n";
		for (int i=0;i<level-1;i++)
			std::cout << "\t";
		std::cout << "}";
	} else {
		if (dynamic_cast<String *>(o))
			std::cout << "\""<<o->toString()<<"\"";
		else std::cout << o->toString();
	}
}

/*! Tries to locate the given __filename__ with the current searchPath set in the runtime.
	@return the path to the file or the original __filename__ if the file could not be found.	*/
static std::string findFile(Runtime & runtime, const std::string & filename){
	static const StringId seachPathsId("__searchPaths");

	std::string file(IO::condensePath(filename));
	if( IO::getEntryType(file)!=IO::TYPE_FILE ){
		if(Array * searchPaths = dynamic_cast<Array*>(runtime.getAttribute(seachPathsId).getValue())){
			for(ERef<Iterator> itRef=searchPaths->getIterator();!itRef->end();itRef->next()){
				ObjRef valueRef = itRef->value();
				std::string s(IO::condensePath(valueRef.toString()+'/'+filename));
				if( IO::getEntryType(s)==IO::TYPE_FILE ){
					file = s;
					break;
				}
			}
		}
	}
	return file;
}

//! (static)
ObjRef StdLib::loadOnce(Runtime & runtime,const std::string & filename){
	static const StringId mapId("__loadOnce_loadedFiles");

	std::string condensedFilename( IO::condensePath(findFile(runtime,filename)) );
	Map * m=dynamic_cast<Map*>(runtime.getAttribute(mapId).getValue());
	if(m==NULL){
		m=Map::create();
		runtime.setAttribute(mapId, Attribute(m));
	}
	ObjRef obj=m->getValue(condensedFilename);
	if(obj.toBool()){ // already loaded?
		return NULL;
	}
	m->setValue(String::create(condensedFilename),Bool::create(true));
	return _loadAndExecute(runtime,condensedFilename);
}

#if defined(_WIN32)
static LARGE_INTEGER _getPerformanceCounter();

// execute this as soon as possible (when the global static variables are initialized)
static LARGE_INTEGER _clockStart = _getPerformanceCounter();

// wrapper for the windows high performance timer.
LARGE_INTEGER _getPerformanceCounter(){
	LARGE_INTEGER c;
	QueryPerformanceCounter(&c);
	return c;
}

#endif

// -------------------------------------------------------------
//! init  (globals)
void StdLib::init(EScript::Namespace * globals) {

	/*!	[ESF] void addSearchPath(path)
		Adds a search path which is used for load(...) and loadOnce(...)	*/
	ES_FUNCTION_DECLARE(globals,"addSearchPath",1,1,{
		static const StringId seachPathsId("__searchPaths");
		Array * searchPaths = dynamic_cast<Array*>(runtime.getAttribute(seachPathsId).getValue());
		if(searchPaths == NULL){
			searchPaths = Array::create();
			runtime.setAttribute(seachPathsId, Attribute(searchPaths));
		}
		searchPaths->pushBack(String::create(parameter[0].toString()));
		return Void::get();
	})

	//! [ESF] void assert( expression[,text])
	ES_FUNCTION_DECLARE(globals,"assert",1,2, {
		assertParamCount(runtime,parameter.count(),1,2);
		if(!parameter[0]->toBool()){
			runtime.setException(parameter.count()>1?parameter[1]->toString():"Assert failed.");
		}
		return NULL;
	})

	//! [ESF]  string chr(number)
	ES_FUNCTION_DECLARE(globals,"chr",1,1,{
		std::ostringstream s;
		s<< static_cast<char>(parameter[0]->toInt());
		return String::create(s.str());
	})

	// clock
	{
	#if defined(_WIN32)
	typedef LARGE_INTEGER timer_t;
	static timer_t frequency;
	if(!QueryPerformanceFrequency(&frequency)) {
		std::cout <<("QueryPerformanceFrequency failed, timer will not work properly!");
	}

	//! [ESF]  number clock()
	ES_FUNCTION_DECLARE(globals,"clock",0,0,{
		LARGE_INTEGER time = _getPerformanceCounter();
		return Number::create( static_cast<double>(time.QuadPart-_clockStart.QuadPart) / static_cast<double>(frequency.QuadPart) );
	})

	#else
	//! [ESF]  number clock()
	ESF_DECLARE(globals,"clock",0,0,Number::create( static_cast<double>(clock())/CLOCKS_PER_SEC))
	#endif
	}

	//!	[ESF]  Object eval(string)
	ESF_DECLARE(globals,"eval",1,1,
				_eval(runtime,CodeFragment(Consts::FILENAME_INLINE, StringData(parameter[0].toString()))).detachAndDecrease())

	/*!	[ESF]  Map getDate([time])
		like http://de3.php.net/manual/de/function.getdate.php	*/
	ES_FUNCTION_DECLARE(globals,"getDate",0,1,{
		time_t t=(parameter.count()==0)?time(0):static_cast<time_t>(parameter[0]->toInt());
		tm *d=localtime (& t );
		Map * m=Map::create();
		m->setValue(String::create("seconds"),Number::create(d->tm_sec));
		m->setValue(String::create("minutes"),Number::create(d->tm_min));
		m->setValue(String::create("hours"),Number::create(d->tm_hour));
		m->setValue(String::create("mday"),Number::create(d->tm_mday));
		m->setValue(String::create("mon"),Number::create(d->tm_mon+1));
		m->setValue(String::create("year"),Number::create(d->tm_year+1900));
		m->setValue(String::create("wday"),Number::create(d->tm_wday));
		m->setValue(String::create("yday"),Number::create(d->tm_yday));
		m->setValue(String::create("isdst"),Number::create(d->tm_isdst));
		return m;
	})

	//! [ESF]  string getOS()
	ESF_DECLARE(globals,"getOS",0,0,String::create(StdLib::getOS()))

	//! [ESF] Runtime getRuntime( )
	ESF_DECLARE(globals,"getRuntime",0,0, &runtime)

	//!	[ESF] mixed load(string filename)
	ESF_DECLARE(globals,"load",1,1,_loadAndExecute(runtime,findFile(runtime,parameter[0].toString())).detachAndDecrease())

	//!	[ESF] mixed loadOnce(string filename)
	ESF_DECLARE(globals,"loadOnce",1,1,StdLib::loadOnce(runtime,parameter[0].toString()).detachAndDecrease())

	//! [ESF] void out(...)
	ES_FUNCTION_DECLARE(globals,"out",0,-1, {
		for(ParameterValues::const_iterator it=parameter.begin();it!=parameter.end();++it)
			std::cout << (*it).toString();
		std::cout.flush();
		return NULL;
	})

	//! [ESF] void out(...)
	ES_FUNCTION_DECLARE(globals,"outln",0,-1, {
		for(ParameterValues::const_iterator it=parameter.begin();it!=parameter.end();++it)
			std::cout << (*it).toString();
		std::cout << std::endl;
		std::cout.flush();
		return NULL;
	})

	//!	[ESF]  BlockStatement parse(string) @deprecated
	ES_FUNCTION_DECLARE(globals,"parse",1,1, {
		ERef<UserFunction> script;

		Compiler compiler(runtime.getLogger());
		script = compiler.compile(CodeFragment(Consts::FILENAME_INLINE, StringData(parameter[0].toString())));

		return script.detachAndDecrease();
	})
	//! [ESF]  obj parseJSON(string)
	ESF_DECLARE(globals,"parseJSON",1,1,JSON::parseJSON(parameter[0].toString()))

	//! [ESF] void print_r(...)
	ES_FUNCTION_DECLARE(globals,"print_r",0,-1, {
		std::cout << "\n";
		for(ParameterValues::const_iterator it=parameter.begin();it!=parameter.end();++it) {
			if (!(*it).isNull())
				print_r((*it).get());
		}
		return NULL;
	})

	//!	[ESF]  number system(command)
	ESF_DECLARE(globals,"system",1,1,Number::create(system(parameter[0]->toString().c_str())))

	//!	[ESF] Number exec(String path, Array argv)
	ES_FUNCTION_DECLARE(globals, "exec", 2, 2, {
		Array * array = assertType<Array>(runtime, parameter[1]);
		uint32_t argc = array->size();

		char ** argv  = new char *[argc + 1];
		for(uint_fast32_t i = 0; i < argc; ++i) {
			 std::string arg = array->get(i)->toString();
			 argv[i] = new char[arg.length() + 1];
			 std::copy(arg.begin(), arg.end(), argv[i]);
			 argv[i][arg.length()] = '\0';
		}
		argv[argc] = NULL;

		Number * result = Number::create(execv(parameter[0]->toString().c_str(), argv));

		for(uint_fast32_t i = 0; i < argc; ++i) {
			delete [] argv[i];
		}
		delete [] argv;

		return result;
	})

	//! [ESF]  number time()
	ESF_DECLARE(globals,"time",0,0,Number::create(static_cast<double>(time(NULL))))

	//! [ESF]  string toJSON(obj[,formatted=true])
	ESF_DECLARE(globals,"toJSON",1,2,String::create(JSON::toJSON(parameter[0].get(),parameter[1].toBool(true))))

}

}
<commit_msg>...<commit_after>// StdLib.cpp
// This file is part of the EScript programming language.
// See copyright notice in EScript.h
// ------------------------------------------------------
#include "StdLib.h"

#include "../EScript/EScript.h"
#include "../EScript/Parser/Compiler.h"
#include "../EScript/Parser/Parser.h"
#include "../EScript/Utils/IO/IO.h"
#include "ext/JSON.h"

#include <sstream>
#include <stdlib.h>
#include <ctime>
#include <unistd.h>

#if defined(_WIN32)
#include <windows.h>
#endif

namespace EScript{

std::string StdLib::getOS(){
	#if defined(_WIN32) || defined(_WIN64)
	return std::string("WINDOWS");
	#elif defined(__APPLE__)
	return std::string("MAC OS");
	#elif defined(__linux__)
	return std::string("LINUX");
	#elif defined(__unix__)
	return std::string("UNIX");
	#else
	return std::string("UNKNOWN");
	#endif
}

//! (static)
void StdLib::print_r(Object * o,int maxLevel,int level) {
	if (!o) return;
	if (level>maxLevel) {
		std::cout << " ... \n";
		return;
	}

	if (Array * a=dynamic_cast<Array *>(o)) {
		std::cout << "[\n";
		ERef<Iterator> itRef=a->getIterator();
		int nr=0;
		while (!itRef->end()) {
			ObjRef valueRef=itRef->value();
			ObjRef keyRef=itRef->key();
			if (nr++>0)std::cout << ",\n";
			if (!valueRef.isNull()) {
				for (int i=0;i<level;i++)
					std::cout << "\t";
				std::cout << "["<<keyRef.toString() <<"] : ";
				print_r(valueRef.get(),maxLevel,level+1);

			}
			itRef->next();
		}
		std::cout << "\n";
		for (int i=0;i<level-1;i++)
			std::cout << "\t";
		std::cout << "]";
	} else if (Map * m=dynamic_cast<Map *>(o)) {
		std::cout << "{\n";
		ERef<Iterator> itRef=m->getIterator();
		int nr=0;
		while (!itRef->end()) {
			ObjRef valueRef=itRef->value();
			ObjRef keyRef=itRef->key();
			if (nr++>0)
				std::cout << ",\n";
			if (!valueRef.isNull()) {
				for (int i=0;i<level;i++)
					std::cout << "\t";
				std::cout << "["<<keyRef.toString() <<"] : ";
				print_r(valueRef.get(),maxLevel,level+1);

			}

			itRef->next();
		}
		std::cout << "\n";
		for (int i=0;i<level-1;i++)
			std::cout << "\t";
		std::cout << "}";
	} else {
		if (dynamic_cast<String *>(o))
			std::cout << "\""<<o->toString()<<"\"";
		else std::cout << o->toString();
	}
}

/*! Tries to locate the given __filename__ with the current searchPath set in the runtime.
	@return the path to the file or the original __filename__ if the file could not be found.	*/
static std::string findFile(Runtime & runtime, const std::string & filename){
	static const StringId seachPathsId("__searchPaths");

	std::string file(IO::condensePath(filename));
	if( IO::getEntryType(file)!=IO::TYPE_FILE ){
		if(Array * searchPaths = dynamic_cast<Array*>(runtime.getAttribute(seachPathsId).getValue())){
			for(ERef<Iterator> itRef=searchPaths->getIterator();!itRef->end();itRef->next()){
				ObjRef valueRef = itRef->value();
				std::string s(IO::condensePath(valueRef.toString()+'/'+filename));
				if( IO::getEntryType(s)==IO::TYPE_FILE ){
					file = s;
					break;
				}
			}
		}
	}
	return file;
}

//! (static)
ObjRef StdLib::loadOnce(Runtime & runtime,const std::string & filename){
	static const StringId mapId("__loadOnce_loadedFiles");

	std::string condensedFilename( IO::condensePath(findFile(runtime,filename)) );
	Map * m=dynamic_cast<Map*>(runtime.getAttribute(mapId).getValue());
	if(m==NULL){
		m=Map::create();
		runtime.setAttribute(mapId, Attribute(m));
	}
	ObjRef obj=m->getValue(condensedFilename);
	if(obj.toBool()){ // already loaded?
		return NULL;
	}
	m->setValue(String::create(condensedFilename),Bool::create(true));
	return _loadAndExecute(runtime,condensedFilename);
}

#if defined(_WIN32)
static LARGE_INTEGER _getPerformanceCounter();

// execute this as soon as possible (when the global static variables are initialized)
static LARGE_INTEGER _clockStart = _getPerformanceCounter();

// wrapper for the windows high performance timer.
LARGE_INTEGER _getPerformanceCounter(){
	LARGE_INTEGER c;
	QueryPerformanceCounter(&c);
	return c;
}

#endif

// -------------------------------------------------------------
//! init  (globals)
void StdLib::init(EScript::Namespace * globals) {

	/*!	[ESF] void addSearchPath(path)
		Adds a search path which is used for load(...) and loadOnce(...)	*/
	ES_FUNCTION_DECLARE(globals,"addSearchPath",1,1,{
		static const StringId seachPathsId("__searchPaths");
		Array * searchPaths = dynamic_cast<Array*>(runtime.getAttribute(seachPathsId).getValue());
		if(searchPaths == NULL){
			searchPaths = Array::create();
			runtime.setAttribute(seachPathsId, Attribute(searchPaths));
		}
		searchPaths->pushBack(String::create(parameter[0].toString()));
		return Void::get();
	})

	//! [ESF] void assert( expression[,text])
	ES_FUNCTION_DECLARE(globals,"assert",1,2, {
		assertParamCount(runtime,parameter.count(),1,2);
		if(!parameter[0]->toBool()){
			runtime.setException(parameter.count()>1?parameter[1]->toString():"Assert failed.");
		}
		return NULL;
	})

	//! [ESF]  string chr(number)
	ES_FUNCTION_DECLARE(globals,"chr",1,1,{
		std::ostringstream s;
		s<< static_cast<char>(parameter[0]->toInt());
		return String::create(s.str());
	})

	// clock
	{
	#if defined(_WIN32)
	typedef LARGE_INTEGER timer_t;
	static timer_t frequency;
	if(!QueryPerformanceFrequency(&frequency)) {
		std::cout <<("QueryPerformanceFrequency failed, timer will not work properly!");
	}

	//! [ESF]  number clock()
	ES_FUNCTION_DECLARE(globals,"clock",0,0,{
		LARGE_INTEGER time = _getPerformanceCounter();
		return Number::create( static_cast<double>(time.QuadPart-_clockStart.QuadPart) / static_cast<double>(frequency.QuadPart) );
	})

	#else
	//! [ESF]  number clock()
	ESF_DECLARE(globals,"clock",0,0,Number::create( static_cast<double>(clock())/CLOCKS_PER_SEC))
	#endif
	}

	//!	[ESF]  Object eval(string)
	ESF_DECLARE(globals,"eval",1,1,
				_eval(runtime,CodeFragment(Consts::FILENAME_INLINE, StringData(parameter[0].toString()))).detachAndDecrease())

	/*!	[ESF]  Map getDate([time])
		like http://de3.php.net/manual/de/function.getdate.php	*/
	ES_FUNCTION_DECLARE(globals,"getDate",0,1,{
		time_t t=(parameter.count()==0)?time(0):static_cast<time_t>(parameter[0]->toInt());
		tm *d=localtime (& t );
		Map * m=Map::create();
		m->setValue(String::create("seconds"),Number::create(d->tm_sec));
		m->setValue(String::create("minutes"),Number::create(d->tm_min));
		m->setValue(String::create("hours"),Number::create(d->tm_hour));
		m->setValue(String::create("mday"),Number::create(d->tm_mday));
		m->setValue(String::create("mon"),Number::create(d->tm_mon+1));
		m->setValue(String::create("year"),Number::create(d->tm_year+1900));
		m->setValue(String::create("wday"),Number::create(d->tm_wday));
		m->setValue(String::create("yday"),Number::create(d->tm_yday));
		m->setValue(String::create("isdst"),Number::create(d->tm_isdst));
		return m;
	})

	//! [ESF]  string getOS()
	ESF_DECLARE(globals,"getOS",0,0,String::create(StdLib::getOS()))

	//! [ESF] Runtime getRuntime( )
	ESF_DECLARE(globals,"getRuntime",0,0, &runtime)

	//!	[ESF] mixed load(string filename)
	ESF_DECLARE(globals,"load",1,1,_loadAndExecute(runtime,findFile(runtime,parameter[0].toString())).detachAndDecrease())

	//!	[ESF] mixed loadOnce(string filename)
	ESF_DECLARE(globals,"loadOnce",1,1,StdLib::loadOnce(runtime,parameter[0].toString()).detachAndDecrease())

	//! [ESF] void out(...)
	ES_FUNCTION_DECLARE(globals,"out",0,-1, {
		for(ParameterValues::const_iterator it=parameter.begin();it!=parameter.end();++it)
			std::cout << (*it).toString();
		std::cout.flush();
		return NULL;
	})

	//! [ESF] void outln(...)
	ES_FUNCTION_DECLARE(globals,"outln",0,-1, {
		for(ParameterValues::const_iterator it=parameter.begin();it!=parameter.end();++it)
			std::cout << (*it).toString();
		std::cout << std::endl;
		std::cout.flush();
		return NULL;
	})

	//!	[ESF]  BlockStatement parse(string) @deprecated
	ES_FUNCTION_DECLARE(globals,"parse",1,1, {
		ERef<UserFunction> script;

		Compiler compiler(runtime.getLogger());
		script = compiler.compile(CodeFragment(Consts::FILENAME_INLINE, StringData(parameter[0].toString())));

		return script.detachAndDecrease();
	})
	//! [ESF]  obj parseJSON(string)
	ESF_DECLARE(globals,"parseJSON",1,1,JSON::parseJSON(parameter[0].toString()))

	//! [ESF] void print_r(...)
	ES_FUNCTION_DECLARE(globals,"print_r",0,-1, {
		std::cout << "\n";
		for(ParameterValues::const_iterator it=parameter.begin();it!=parameter.end();++it) {
			if (!(*it).isNull())
				print_r((*it).get());
		}
		return NULL;
	})

	//!	[ESF]  number system(command)
	ESF_DECLARE(globals,"system",1,1,Number::create(system(parameter[0]->toString().c_str())))

	//!	[ESF] Number exec(String path, Array argv)
	ES_FUNCTION_DECLARE(globals, "exec", 2, 2, {
		Array * array = assertType<Array>(runtime, parameter[1]);
		uint32_t argc = array->size();

		char ** argv  = new char *[argc + 1];
		for(uint_fast32_t i = 0; i < argc; ++i) {
			 std::string arg = array->get(i)->toString();
			 argv[i] = new char[arg.length() + 1];
			 std::copy(arg.begin(), arg.end(), argv[i]);
			 argv[i][arg.length()] = '\0';
		}
		argv[argc] = NULL;

		Number * result = Number::create(execv(parameter[0]->toString().c_str(), argv));

		for(uint_fast32_t i = 0; i < argc; ++i) {
			delete [] argv[i];
		}
		delete [] argv;

		return result;
	})

	//! [ESF]  number time()
	ESF_DECLARE(globals,"time",0,0,Number::create(static_cast<double>(time(NULL))))

	//! [ESF]  string toJSON(obj[,formatted=true])
	ESF_DECLARE(globals,"toJSON",1,2,String::create(JSON::toJSON(parameter[0].get(),parameter[1].toBool(true))))

}

}
<|endoftext|>


<commit_before>#include <iostream>
#include <fstream>

#include "openeye.h"
#include "oesystem.h"
#include "oechem.h"
#include "oedocking.h"

using namespace OESystem;
using namespace OEChem;
using namespace OEDocking;
using namespace std;

int main(int numOfArg, char* argv[])
{
	OEGraphMol receptor;
	OEReadReceptorFile(receptor, argv[3]);
    unsigned int dockMethod = atoi(argv[1]);
	unsigned int dockResolution = atoi(argv[2]);
	OEDock dock(dockMethod, dockResolution);
	dock.Initialize(receptor);

	oemolistream imstr;
	oemolostream omstr;

	imstr.SetFormat(OEFormat::SDF);
	omstr.SetFormat(OEFormat::SDF);

	OEMol mcmol;
	//Scoring the molecules in SDF File
	         while (OEReadMolecule(imstr, mcmol))
	         {
	           OEGraphMol dockedMol;
	           dock.DockMultiConformerMolecule(dockedMol,mcmol);
	           string sdtag = OEDockMethodGetName(dockMethod);
	           OESetSDScore(dockedMol, dock, sdtag);
	           dock.AnnotatePose(dockedMol);
	           //Writing moles to the SDF File with Scores
	           OEWriteMolecule(omstr, dockedMol);
	         }
    return 0;
}
<commit_msg>Update dockingstd.cpp<commit_after>#include <iostream>
#include <fstream>

#include "openeye.h"
#include "oesystem.h"
#include "oechem.h"
#include "oedocking.h"

using namespace OESystem;
using namespace OEChem;
using namespace OEDocking;
using namespace std;

int main(int numOfArg, char* argv[])
{
	OEGraphMol receptor;
	OEReadReceptorFile(receptor, argv[3]);
    	unsigned int dockMethod = atoi(argv[1]);
	unsigned int dockResolution = atoi(argv[2]);
	OEDock dock(dockMethod, dockResolution);
	dock.Initialize(receptor);

	oemolistream imstr;
	oemolostream omstr;

	imstr.SetFormat(OEFormat::SDF);
	omstr.SetFormat(OEFormat::SDF);

	OEMol mcmol;
	//Scoring the molecules in SDF File
	         while (OEReadMolecule(imstr, mcmol))
	         {
	           OEGraphMol dockedMol;
	           dock.DockMultiConformerMolecule(dockedMol,mcmol);
	           string sdtag = OEDockMethodGetName(dockMethod);
	           OESetSDScore(dockedMol, dock, sdtag);
	           dock.AnnotatePose(dockedMol);
	           //Writing moles to the SDF File with Scores
	           OEWriteMolecule(omstr, dockedMol);
	         }
    return 0;
}
<|endoftext|>


<commit_before>#include "rpc/rpc_connection_limits.h"

namespace smf {
rpc_connection_limits::rpc_connection_limits(size_t basic_req_size,
                                             size_t bloat_mult,
                                             size_t max_mem)
  : basic_request_size(basic_req_size)
  , bloat_factor(bloat_mult)
  , max_memory(max_mem)
  , resources_available(max_mem) {}

size_t rpc_connection_limits::estimate_request_size(size_t serialized_size) {
  return (basic_request_size + serialized_size) * bloat_factor;
}

future<> rpc_connection_limits::wait_for_resources(size_t memory_consumed) {
  return resources_available.wait(memory_consumed);
}
void rpc_connection_limits::release_resources(size_t memory_consumed) {
  resources_available.signal(memory_consumed);
}

rpc_connection_limits::~rpc_connection_limits() {}

std::ostream &operator<<(std::ostream &o, const rpc_connection_limits &l) {
  o << "{'basic_request_size':" << l.basic_request_size
    << ",'bloat_factor': " << l.bloat_factor << ",'max_mem':" << l.max_memory
    << ",'resources_available':" << l.resources_available.current() << "}";
  return o;
}
} // smf
<commit_msg>rpc: rpc_connection_limits.cc formatted output<commit_after>#include "rpc/rpc_connection_limits.h"

namespace smf {
rpc_connection_limits::rpc_connection_limits(size_t basic_req_size,
                                             size_t bloat_mult,
                                             size_t max_mem)
  : basic_request_size(basic_req_size)
  , bloat_factor(bloat_mult)
  , max_memory(max_mem)
  , resources_available(max_mem) {}

size_t rpc_connection_limits::estimate_request_size(size_t serialized_size) {
  return (basic_request_size + serialized_size) * bloat_factor;
}

future<> rpc_connection_limits::wait_for_resources(size_t memory_consumed) {
  return resources_available.wait(memory_consumed);
}
void rpc_connection_limits::release_resources(size_t memory_consumed) {
  resources_available.signal(memory_consumed);
}

rpc_connection_limits::~rpc_connection_limits() {}

std::ostream &operator<<(std::ostream &o, const rpc_connection_limits &l) {
  o << "{'basic_req_size':" << l.basic_request_size
    << ",'bloat_factor': " << l.bloat_factor << ",'max_mem':" << l.max_memory
    << ",'res_avail':" << l.resources_available.current() << "}";
  return o;
}
} // smf
<|endoftext|>


<commit_before>#include "HalideRuntime.h"
#include "runtime_internal.h"

extern "C" {

WEAK __attribute__((always_inline)) int halide_profiler_set_current_func(halide_profiler_state *state, int tok, int t) {
    // Do a volatile store to discourage llvm from reordering it.
    volatile int *ptr = &(state->current_func);
    *ptr = tok + t;
    return 0;
}

}
<commit_msg>Fix profiler performance test<commit_after>#include "HalideRuntime.h"
#include "runtime_internal.h"

extern "C" {

WEAK __attribute__((always_inline)) int halide_profiler_set_current_func(halide_profiler_state *state, int tok, int t) {
    // Use empty volatile asm blocks to prevent code motion. Otherwise
    // llvm reorders or elides the stores.
    int *ptr = &(state->current_func);
    asm volatile ("":::);
    *ptr = tok + t;
    asm volatile ("":::);
    return 0;
}

}
<|endoftext|>


<commit_before>#include "TROOT.h"
#include "TSystem.h"
#include "TRolke.h"
#include "Riostream.h"

void Rolke()
{
//////////////////////////////////////////////////
// Routine computes the profile likelihood confidence
// limits for  7 different model assumptions
// on systematic/statistical uncertainties
//
// You must load libPhysics before executing this script.
//
// Author : Jan Conrad (CERN) <Jan.Conrad@cern.ch>
//////////////////////////////////////////////////

/////////////////////////////////////////////////////////////
// Model 1 assumes:
//
// Poisson uncertainty in the background estimate
// Binomial uncertainty in the efficiency estimate
//
// y = 10      events observed in the background region
// x = 5       events in the signal region
// tau = 2.5   ratio between size of signal/background region
// m = 100     MC events have been produced  (signal)
// z = 50      MC events have been observed (signal)
// alpha = 0.9 Confidence Level
//////////////////////////////////////////////////////////////

    //gSystem->Load("libPhysics");
 Double_t bm = 0.0;
 Double_t tau = 2.5;
 Int_t mid = 1;
 Int_t m = 100;
 Int_t z = 50;
 Int_t y = 10;
 Int_t x = 5;
 // Initialize parameters not used.
 Double_t e = 0.0;
 Double_t em = 0.0;
 Double_t sde=0.0;
 Double_t sdb=0.0;
 Double_t b = 0.0;

 TRolke g;

 g.SetCL(0.90);

 Double_t ul = g.CalculateInterval(x,y,z,bm,em,e,mid,sde,sdb,tau,b,m);
 Double_t ll = g.GetLowerLimit();

 cout << "Assuming Model 1" << endl;
 cout <<  "the Profile Likelihood interval is :" << endl;
 cout << "[" << ll << "," << ul << "]" << endl;

/////////////////////////////////////////////////////////////
// Model 2 assumes:
//
// Poisson uncertainty in the background estimate
// Gaussian  uncertainty in the efficiency estimate
//
// y = 3        events observed in the background region
// x = 10       events in the signal region
// tau = 2.5    ratio between size of signal/background region
// em = 0.9     measured efficiency
// sde = 0.05   standard deviation of efficiency
// alpha =0.95  Confidence L evel
//////////////////////////////////////////////////////////////

 tau = 2.5;
 mid = 2;
 y = 3;
 x = 10;
 em=0.9;
 sde=0.05;

 g.SetCL(0.95);

 ul = g.CalculateInterval(x,y,z,bm,em,e,mid,sde,sdb,tau,b,m);
 ll = g.GetLowerLimit();

  cout << "Assuming MODEL 2" << endl;
  cout <<  "the Profile Likelihood interval is :" << endl;
  cout << "[" << ll << "," << ul << "]" << endl;

/////////////////////////////////////////////////////////////
// Model 3 assumes:
//
// Gaussian uncertainty in the background estimate
// Gaussian  uncertainty in the efficiency estimate
//
// bm = 5       expected background
// x = 10       events in the signal region
// sdb = 0.5    standard deviation in background estimate
// em = 0.9     measured efficiency
// sde = 0.05   standard deviation of efficiency
// alpha =0.99 Confidence Level
//////////////////////////////////////////////////////////////

 mid = 3;
 bm = 5.0;
 x = 10;
 em = 0.9;
 sde=0.05;
 sdb=0.5;

 g.SetCL(0.99);

 ul = g.CalculateInterval(x,y,z,bm,em,e,mid,sde,sdb,tau,b,m);
 ll = g.GetLowerLimit();

cout << "Assuming Model 3" << endl;
cout <<  "the Profile Likelihood interval is :" << endl;
cout << "[" << ll << "," << ul << "]" << endl;

/////////////////////////////////////////////////////////////
// Model 4 assumes:
//
// Poisson uncertainty in the background estimate
// known efficiency
//
// y = 7       events observed in the background region
// x = 1       events in the signal region
// tau = 5     ratio between size of signal/background region
//
// alpha =0.68  Confidence L evel
//////////////////////////////////////////////////////////////

 tau = 5;
 mid = 4;
 y = 7;
 x = 1;
 e = 0.25;

 g.SetCL(0.68);

 ul = g.CalculateInterval(x,y,z,bm,em,e,mid,sde,sdb,tau,b,m);
 ll = g.GetLowerLimit();

  cout << "Assuming Model 4" << endl;
    cout <<  "the Profile Likelihood interval is :" << endl;
  cout << "[" << ll << "," << ul << "]" << endl;

////////////////////////////////////////////////////////
// Model 5 assumes:
//
// Gaussian uncertainty in the background estimate
// Known efficiency
//
// bm = 0           measured background expectation
// x = 1            events in the signal region
// e = 0.65
// sdb = 1.         standard deviation of background estimate
// alpha =0.799999  Confidence Level
///////////////////////////////////////////////////////

 mid = 5;
 bm = 0.0;
 x = 1;
 e = 0.65;
 sdb=1.0;

 g.SetCL(0.80);

 ul = g.CalculateInterval(x,y,z,bm,em,e,mid,sde,sdb,tau,b,m);
 ll = g.GetLowerLimit();

  cout << "Assuming Model 5" << endl;
  cout <<  "the Profile Likelihood interval is :" << endl;
  cout << "[" << ll << "," << ul << "]" << endl;

////////////////////////////////////////////////////////
// Model 6 assumes:
//
// Known background
// Binomial uncertainty in the efficiency estimate
//
// b = 10       known background
// x = 25       events in the signal region
// z = 500      Number of observed signal MC events
// m = 750      Number of produced MC signal events
// alpha =0.9   Confidence L evel
///////////////////////////////////////////////////////

 y = 1;
 mid = 6;
 m = 750;
 z = 500;
 x = 25;
 b = 10.0;

 TRolke p;
 p.SetCL(0.90);
 ul = p.CalculateInterval(x,y,z,bm,em,e,mid,sde,sdb,tau,b,m);
 Double_t newll = p.GetLowerLimit();

  cout << "Assuming Model 6" << endl;
  cout <<  "the Profile Likelihood interval is :" << endl;
  cout << "[" << newll << "," << ul << "]" << endl;

////////////////////////////////////////////////////////
// Model 7 assumes:
//
// Known Background
// Gaussian  uncertainty in the efficiency estimate
//
// x = 15       events in the signal region
// em = 0.77    measured efficiency
// sde = 0.15   standard deviation of efficiency estimate
// b = 10       known background
// alpha =0.95  Confidence L evel
///////////////////////////////////////////////////////

 mid = 7;
 x = 15;
 em = 0.77;
 sde=0.15;
 b = 10.0;

 g.SetCL(0.95);

  ul = g.CalculateInterval(x,y,z,bm,em,e,mid,sde,sdb,tau,b,m);
  ll = g.GetLowerLimit();

  cout << "Assuming Model 7 " << endl;
  cout <<  "the Profile Likelihood interval is :" << endl;
  cout << "[" << ll << "," << ul << "]" << endl;

////////////////////////////////////////////////////////
// Example of bounded and unbounded likelihood
//
// Example for Model 1
///////////////////////////////////////////////////////

 Double_t bm = 0.0;
 Double_t tau = 5;
 Int_t mid = 1;
 Int_t m = 100;
 Int_t z = 90;
 Int_t y = 15;
 Int_t x = 0;
 // Initialize parameters not used.
 Double_t e = 0.0;
 Double_t em = 0.0;
 Double_t sde=0.0;
 Double_t sdb=0.0;
 Double_t b = 0.0;

 TRolke g;

 g.SetCL(0.90);
 g.SetSwitch(1); //bounded

 Double_t ul = g.CalculateInterval(x,y,z,bm,em,e,mid,sde,sdb,tau,b,m);
 Double_t ll = g.GetLowerLimit();

 g.SetSwitch(0); //unbounded

 cout << "Assuming Model 1" << endl;
 cout <<  "the BOUNDED Profile Likelihood interval is :" << endl;
 cout << "[" << ll << "," << ul << "]" << endl;

  ul = g.CalculateInterval(x,y,z,bm,em,e,mid,sde,sdb,tau,b,m);
  ll = g.GetLowerLimit();

 cout << "Assuming Model 1" << endl;
 cout <<  "the UNBOUNDED Profile Likelihood interval is :" << endl;
 cout << "[" << ll << "," << ul << "]" << endl;

}

<commit_msg>From Anna Kreshuk: New version of the tutorial that can also be run with ACLIC<commit_after>#include "TROOT.h"
#include "TSystem.h"
#include "TRolke.h"
#include "Riostream.h"

void Rolke()
{
//////////////////////////////////////////////////
// Routine computes the profile likelihood confidence
// limits for  7 different model assumptions
// on systematic/statistical uncertainties
//
// You must load libPhysics before executing this script.
//
// Author : Jan Conrad (CERN) <Jan.Conrad@cern.ch>
//////////////////////////////////////////////////

/////////////////////////////////////////////////////////////
// Model 1 assumes:
//
// Poisson uncertainty in the background estimate
// Binomial uncertainty in the efficiency estimate
//
// y = 10      events observed in the background region
// x = 5       events in the signal region
// tau = 2.5   ratio between size of signal/background region
// m = 100     MC events have been produced  (signal)
// z = 50      MC events have been observed (signal)
// alpha = 0.9 Confidence Level
//////////////////////////////////////////////////////////////

    //gSystem->Load("libPhysics");
 Double_t bm = 0.0;
 Double_t tau = 2.5;
 Int_t mid = 1;
 Int_t m = 100;
 Int_t z = 50;
 Int_t y = 10;
 Int_t x = 5;
 // Initialize parameters not used.
 Double_t e = 0.0;
 Double_t em = 0.0;
 Double_t sde=0.0;
 Double_t sdb=0.0;
 Double_t b = 0.0;

 TRolke g;

 g.SetCL(0.90);

 Double_t ul = g.CalculateInterval(x,y,z,bm,em,e,mid,sde,sdb,tau,b,m);
 Double_t ll = g.GetLowerLimit();

 cout << "Assuming Model 1" << endl;
 cout <<  "the Profile Likelihood interval is :" << endl;
 cout << "[" << ll << "," << ul << "]" << endl;

/////////////////////////////////////////////////////////////
// Model 2 assumes:
//
// Poisson uncertainty in the background estimate
// Gaussian  uncertainty in the efficiency estimate
//
// y = 3        events observed in the background region
// x = 10       events in the signal region
// tau = 2.5    ratio between size of signal/background region
// em = 0.9     measured efficiency
// sde = 0.05   standard deviation of efficiency
// alpha =0.95  Confidence L evel
//////////////////////////////////////////////////////////////

 tau = 2.5;
 mid = 2;
 y = 3;
 x = 10;
 em=0.9;
 sde=0.05;

 g.SetCL(0.95);

 ul = g.CalculateInterval(x,y,z,bm,em,e,mid,sde,sdb,tau,b,m);
 ll = g.GetLowerLimit();

  cout << "Assuming MODEL 2" << endl;
  cout <<  "the Profile Likelihood interval is :" << endl;
  cout << "[" << ll << "," << ul << "]" << endl;

/////////////////////////////////////////////////////////////
// Model 3 assumes:
//
// Gaussian uncertainty in the background estimate
// Gaussian  uncertainty in the efficiency estimate
//
// bm = 5       expected background
// x = 10       events in the signal region
// sdb = 0.5    standard deviation in background estimate
// em = 0.9     measured efficiency
// sde = 0.05   standard deviation of efficiency
// alpha =0.99 Confidence Level
//////////////////////////////////////////////////////////////

 mid = 3;
 bm = 5.0;
 x = 10;
 em = 0.9;
 sde=0.05;
 sdb=0.5;

 g.SetCL(0.99);

 ul = g.CalculateInterval(x,y,z,bm,em,e,mid,sde,sdb,tau,b,m);
 ll = g.GetLowerLimit();

cout << "Assuming Model 3" << endl;
cout <<  "the Profile Likelihood interval is :" << endl;
cout << "[" << ll << "," << ul << "]" << endl;

/////////////////////////////////////////////////////////////
// Model 4 assumes:
//
// Poisson uncertainty in the background estimate
// known efficiency
//
// y = 7       events observed in the background region
// x = 1       events in the signal region
// tau = 5     ratio between size of signal/background region
//
// alpha =0.68  Confidence L evel
//////////////////////////////////////////////////////////////

 tau = 5;
 mid = 4;
 y = 7;
 x = 1;
 e = 0.25;

 g.SetCL(0.68);

 ul = g.CalculateInterval(x,y,z,bm,em,e,mid,sde,sdb,tau,b,m);
 ll = g.GetLowerLimit();

  cout << "Assuming Model 4" << endl;
    cout <<  "the Profile Likelihood interval is :" << endl;
  cout << "[" << ll << "," << ul << "]" << endl;

////////////////////////////////////////////////////////
// Model 5 assumes:
//
// Gaussian uncertainty in the background estimate
// Known efficiency
//
// bm = 0           measured background expectation
// x = 1            events in the signal region
// e = 0.65
// sdb = 1.         standard deviation of background estimate
// alpha =0.799999  Confidence Level
///////////////////////////////////////////////////////

 mid = 5;
 bm = 0.0;
 x = 1;
 e = 0.65;
 sdb=1.0;

 g.SetCL(0.80);

 ul = g.CalculateInterval(x,y,z,bm,em,e,mid,sde,sdb,tau,b,m);
 ll = g.GetLowerLimit();

  cout << "Assuming Model 5" << endl;
  cout <<  "the Profile Likelihood interval is :" << endl;
  cout << "[" << ll << "," << ul << "]" << endl;

////////////////////////////////////////////////////////
// Model 6 assumes:
//
// Known background
// Binomial uncertainty in the efficiency estimate
//
// b = 10       known background
// x = 25       events in the signal region
// z = 500      Number of observed signal MC events
// m = 750      Number of produced MC signal events
// alpha =0.9   Confidence L evel
///////////////////////////////////////////////////////

 y = 1;
 mid = 6;
 m = 750;
 z = 500;
 x = 25;
 b = 10.0;

 TRolke p;
 p.SetCL(0.90);
 ul = p.CalculateInterval(x,y,z,bm,em,e,mid,sde,sdb,tau,b,m);
 Double_t newll = p.GetLowerLimit();

  cout << "Assuming Model 6" << endl;
  cout <<  "the Profile Likelihood interval is :" << endl;
  cout << "[" << newll << "," << ul << "]" << endl;

////////////////////////////////////////////////////////
// Model 7 assumes:
//
// Known Background
// Gaussian  uncertainty in the efficiency estimate
//
// x = 15       events in the signal region
// em = 0.77    measured efficiency
// sde = 0.15   standard deviation of efficiency estimate
// b = 10       known background
// alpha =0.95  Confidence L evel
///////////////////////////////////////////////////////

 mid = 7;
 x = 15;
 em = 0.77;
 sde=0.15;
 b = 10.0;

 g.SetCL(0.95);

  ul = g.CalculateInterval(x,y,z,bm,em,e,mid,sde,sdb,tau,b,m);
  ll = g.GetLowerLimit();

  cout << "Assuming Model 7 " << endl;
  cout <<  "the Profile Likelihood interval is :" << endl;
  cout << "[" << ll << "," << ul << "]" << endl;

////////////////////////////////////////////////////////
// Example of bounded and unbounded likelihood
//
// Example for Model 1
///////////////////////////////////////////////////////

   bm = 0.0;
   tau = 5;
   mid = 1;
   m = 100;
   z = 90;
   y = 15;
   x = 0;
 // Initialize parameters not used.
   e = 0.0;
   em = 0.0;
   sde=0.0;
   sdb=0.0;
   b = 0.0;

   g.SetCL(0.90);
   g.SetSwitch(1); //bounded

   ul = g.CalculateInterval(x,y,z,bm,em,e,mid,sde,sdb,tau,b,m);
   ll = g.GetLowerLimit();

   g.SetSwitch(0); //unbounded

   cout << "Assuming Model 1" << endl;
   cout <<  "the BOUNDED Profile Likelihood interval is :" << endl;
   cout << "[" << ll << "," << ul << "]" << endl;

   ul = g.CalculateInterval(x,y,z,bm,em,e,mid,sde,sdb,tau,b,m);
   ll = g.GetLowerLimit();

   cout << "Assuming Model 1" << endl;
   cout <<  "the UNBOUNDED Profile Likelihood interval is :" << endl;
   cout << "[" << ll << "," << ul << "]" << endl;

}

<|endoftext|>


<commit_before>// This file is part of the dune-stuff project:
//   https://github.com/wwu-numerik/dune-stuff
// Copyright holders: Rene Milk, Felix Schindler
// License: BSD 2-Clause License (http://opensource.org/licenses/BSD-2-Clause)

#ifndef DUNE_STUFF_FUNCTIONS_FLATTOP_HH
#define DUNE_STUFF_FUNCTIONS_FLATTOP_HH

#include <dune/common/static_assert.hh>

#include <dune/stuff/common/exceptions.hh>
#include <dune/stuff/common/configuration.hh>
#include <dune/stuff/common/float_cmp.hh>
#include <dune/stuff/common/fvector.hh>
#include <dune/stuff/functions/interfaces.hh>

namespace Dune {
namespace Stuff {
namespace Functions {

/**
 * Based on: Brenner, S. C. and Davis, C. B. and Sung, L.-y.
 *           A partition of unity method for the displacement obstacle problem of clamped Kirchhoff plates
 *           http://dx.doi.org/10.1016/j.cam.2013.09.033
 *           Subsection 2.1.1
 */
template< class E, class D, int d, class R, int r, int rC = 1 >
class FlatTop
  : public LocalizableFunctionInterface< E, D, d, R, r, rC >
{
  FlatTop() { static_assert(AlwaysFalse< E >::value, "Not available for these dimensions!"); }
};

template< class E, class D, int d, class R >
class FlatTop< E, D, d, R, 1, 1 >
  : public GlobalFunctionInterface< E, D, d, R, 1, 1 >
{
  typedef GlobalFunctionInterface< E, D, d, R, 1, 1 > BaseType;
  typedef FlatTop< E, D, d, R, 1, 1 >                 ThisType;

public:
  typedef typename BaseType::EntityType      EntityType;
  typedef typename BaseType::DomainFieldType DomainFieldType;
  static const unsigned int                  dimDomain = BaseType::dimDomain;
  typedef typename BaseType::DomainType      DomainType;
  typedef typename BaseType::RangeFieldType  RangeFieldType;
  static const unsigned int                  dimRange = BaseType::dimRange;
  typedef typename BaseType::RangeType       RangeType;

  typedef Common::FieldVector< DomainFieldType, dimDomain > StuffDomainType;
  typedef Common::FieldVector< RangeFieldType, dimRange >   StuffRangeType;

  static const bool available = true;

  static std::string static_id()
  {
    return BaseType::static_id() + ".flattop";
  }

  static Common::Configuration default_config(const std::string sub_name = "")
  {
    Common::Configuration config;
    config["lower_left"]     = "[0.0 0.0 0.0]";
    config["upper_right"]    = "[1.0 1.0 1.0]";
    config["boundary_layer"] = "[1e-1 1e-1 1e-1]";
    config["value"]          = "1.0";
    config["name"]           = static_id();
    if (sub_name.empty())
      return config;
    else {
      Common::Configuration tmp;
      tmp.add(config, sub_name);
      return tmp;
    }
  } // ... default_config(...)

  static std::unique_ptr< ThisType > create(const Common::Configuration config = default_config(),
                                            const std::string sub_name = static_id())
  {
    // get correct config
    const Common::Configuration cfg = config.has_sub(sub_name) ? config.sub(sub_name) : config;
    const Common::Configuration default_cfg = default_config();
    return Common::make_unique< ThisType >(
          cfg.get("lower_left",     default_cfg.get< DomainType >( "lower_left")),
          cfg.get("upper_right",    default_cfg.get< DomainType >( "upper_right")),
          cfg.get("boundary_layer", default_cfg.get< DomainType >( "boundary_layer")),
          cfg.get("value",          default_cfg.get< RangeType >(  "value")),
          cfg.get("name",           default_cfg.get< std::string >("name")));
  } // ... create(...)

  FlatTop(const StuffDomainType& lower_left,
          const StuffDomainType& upper_right,
          const StuffDomainType& boundary_layer,
          const StuffRangeType& value = default_config().get< StuffRangeType >("value"),
          const std::string name = default_config().get< std::string >("name"))
    : lower_left_(lower_left)
    , upper_right_(upper_right)
    , boundary_layer_(boundary_layer)
    , value_(value)
    , name_(name)
  {
    check_input();
  }

  FlatTop(const ThisType& other)
    : lower_left_(other.lower_left_)
    , upper_right_(other.upper_right_)
    , boundary_layer_(other.boundary_layer_)
    , value_(other.value_)
    , name_(other.name_)
  {}

  ThisType& operator=(const ThisType& other) = delete;

  virtual ~FlatTop() {}

  virtual ThisType* copy() const /*DS_OVERRIDE DS_FINAL*/
  {
    return new ThisType(*this);
  }

  virtual std::string type() const /*DS_OVERRIDE DS_FINAL*/
  {
    return BaseType::static_id() + ".flattop";
  }

  virtual std::string name() const /*DS_OVERRIDE DS_FINAL*/
  {
    return name_;
  }

  virtual size_t order() const
  {
    // could be 3 but I am to lazy
    return 4;
  } // ... order(...)

  virtual void evaluate(const DomainType& xx, RangeType& ret) const
  {
    ret = value_;
    for (size_t dd = 0; dd < dimDomain; ++dd) {
      const auto& left = lower_left_[dd];
      const auto& right = upper_right_[dd];
      const auto& point = xx[dd];
      const auto& delta = boundary_layer_[dd];
      if (point < left - delta) {
        // outside
        ret[0] = 0.0;
        break;
      } else if (point < left + delta) {
        // left boundary layer
        ret[0] *= phi_left((point - (left + delta)) / (2.0*delta));
      } else if (point < right - delta) {
        // inside
        // do nothing (keep value)
      } else if (point < right + delta) {
        // right boundary layer
        ret[0] *= phi_right((point - (right - delta)) / (2.0*delta));
      } else {
        // outside
        ret[0] = 0.0;
        break;
      }
    }
  } // ... evaluate(...)

private:
  void check_input() const
  {
    if (!(Common::FloatCmp::gt(upper_right_, lower_left_)))
      DUNE_THROW(Exceptions::wrong_input_given,
                 "upper_right has to be greater than lower_left!\n"
                 << "lower_left = [" << lower_left_ << "]\n"
                 << "upper_right = [" << upper_right_ << "]");
    if (!(Common::FloatCmp::gt(boundary_layer_, StuffDomainType(0))))
      DUNE_THROW(Exceptions::wrong_input_given,
                 "boundary_layer has to be strictly positive!\n"
                 << "boundary_layer = [" << boundary_layer_ << "]");
    if (Common::FloatCmp::gt(boundary_layer_*2.0, upper_right_ - lower_left_))
      DUNE_THROW(Exceptions::wrong_input_given,
                 "boundary_layer has to be thin enough!\n"
                 "2*boundary_layer = [" << boundary_layer_*2.0 << "]\n"
                 << "upper_right - lower_left = [" << upper_right_ - lower_left_ << "]");
  } // .. check_input(...)

  RangeFieldType phi_left(const RangeFieldType& point) const
  {
    assert(!(point < -1.0));
    assert(!(point > 0.0));
    return std::pow(1.0 + point, 2)*(1.0 - 2.0*point);
  } // ... phi_left(...)

  RangeFieldType phi_right(const RangeFieldType& point) const
  {
    assert(!(point < 0.0));
    assert(!(point > 1.0));
    return std::pow(1.0 - point, 2)*(1.0 + 2.0*point);
  } // ... phi_right(...)

  const StuffDomainType lower_left_;
  const StuffDomainType upper_right_;
  const StuffDomainType boundary_layer_;
  const StuffRangeType value_;
  const std::string name_;
}; // class FlatTop< ..., 1, 1 >

} // namespace Functions
} // namespace Stuff
} // namespace Dune

#endif // DUNE_STUFF_FUNCTIONS_FLATTOP_HH
<commit_msg>[functions.flattop] drop assertions in transition region<commit_after>// This file is part of the dune-stuff project:
//   https://github.com/wwu-numerik/dune-stuff
// Copyright holders: Rene Milk, Felix Schindler
// License: BSD 2-Clause License (http://opensource.org/licenses/BSD-2-Clause)

#ifndef DUNE_STUFF_FUNCTIONS_FLATTOP_HH
#define DUNE_STUFF_FUNCTIONS_FLATTOP_HH

#include <dune/common/static_assert.hh>

#include <dune/stuff/common/exceptions.hh>
#include <dune/stuff/common/configuration.hh>
#include <dune/stuff/common/float_cmp.hh>
#include <dune/stuff/common/fvector.hh>
#include <dune/stuff/functions/interfaces.hh>

namespace Dune {
namespace Stuff {
namespace Functions {

/**
 * Based on: Brenner, S. C. and Davis, C. B. and Sung, L.-y.
 *           A partition of unity method for the displacement obstacle problem of clamped Kirchhoff plates
 *           http://dx.doi.org/10.1016/j.cam.2013.09.033
 *           Subsection 2.1.1
 */
template< class E, class D, int d, class R, int r, int rC = 1 >
class FlatTop
  : public LocalizableFunctionInterface< E, D, d, R, r, rC >
{
  FlatTop() { static_assert(AlwaysFalse< E >::value, "Not available for these dimensions!"); }
};

template< class E, class D, int d, class R >
class FlatTop< E, D, d, R, 1, 1 >
  : public GlobalFunctionInterface< E, D, d, R, 1, 1 >
{
  typedef GlobalFunctionInterface< E, D, d, R, 1, 1 > BaseType;
  typedef FlatTop< E, D, d, R, 1, 1 >                 ThisType;

public:
  typedef typename BaseType::EntityType      EntityType;
  typedef typename BaseType::DomainFieldType DomainFieldType;
  static const unsigned int                  dimDomain = BaseType::dimDomain;
  typedef typename BaseType::DomainType      DomainType;
  typedef typename BaseType::RangeFieldType  RangeFieldType;
  static const unsigned int                  dimRange = BaseType::dimRange;
  typedef typename BaseType::RangeType       RangeType;

  typedef Common::FieldVector< DomainFieldType, dimDomain > StuffDomainType;
  typedef Common::FieldVector< RangeFieldType, dimRange >   StuffRangeType;

  static const bool available = true;

  static std::string static_id()
  {
    return BaseType::static_id() + ".flattop";
  }

  static Common::Configuration default_config(const std::string sub_name = "")
  {
    Common::Configuration config;
    config["lower_left"]     = "[0.0 0.0 0.0]";
    config["upper_right"]    = "[1.0 1.0 1.0]";
    config["boundary_layer"] = "[1e-1 1e-1 1e-1]";
    config["value"]          = "1.0";
    config["name"]           = static_id();
    if (sub_name.empty())
      return config;
    else {
      Common::Configuration tmp;
      tmp.add(config, sub_name);
      return tmp;
    }
  } // ... default_config(...)

  static std::unique_ptr< ThisType > create(const Common::Configuration config = default_config(),
                                            const std::string sub_name = static_id())
  {
    // get correct config
    const Common::Configuration cfg = config.has_sub(sub_name) ? config.sub(sub_name) : config;
    const Common::Configuration default_cfg = default_config();
    return Common::make_unique< ThisType >(
          cfg.get("lower_left",     default_cfg.get< DomainType >( "lower_left")),
          cfg.get("upper_right",    default_cfg.get< DomainType >( "upper_right")),
          cfg.get("boundary_layer", default_cfg.get< DomainType >( "boundary_layer")),
          cfg.get("value",          default_cfg.get< RangeType >(  "value")),
          cfg.get("name",           default_cfg.get< std::string >("name")));
  } // ... create(...)

  FlatTop(const StuffDomainType& lower_left,
          const StuffDomainType& upper_right,
          const StuffDomainType& boundary_layer,
          const StuffRangeType& value = default_config().get< StuffRangeType >("value"),
          const std::string name = default_config().get< std::string >("name"))
    : lower_left_(lower_left)
    , upper_right_(upper_right)
    , boundary_layer_(boundary_layer)
    , value_(value)
    , name_(name)
  {
    check_input();
  }

  FlatTop(const ThisType& other)
    : lower_left_(other.lower_left_)
    , upper_right_(other.upper_right_)
    , boundary_layer_(other.boundary_layer_)
    , value_(other.value_)
    , name_(other.name_)
  {}

  ThisType& operator=(const ThisType& other) = delete;

  virtual ~FlatTop() {}

  virtual ThisType* copy() const /*DS_OVERRIDE DS_FINAL*/
  {
    return new ThisType(*this);
  }

  virtual std::string type() const /*DS_OVERRIDE DS_FINAL*/
  {
    return BaseType::static_id() + ".flattop";
  }

  virtual std::string name() const /*DS_OVERRIDE DS_FINAL*/
  {
    return name_;
  }

  virtual size_t order() const
  {
    // could be 3 but I am to lazy
    return 4;
  } // ... order(...)

  virtual void evaluate(const DomainType& xx, RangeType& ret) const
  {
    ret = value_;
    for (size_t dd = 0; dd < dimDomain; ++dd) {
      const auto& left = lower_left_[dd];
      const auto& right = upper_right_[dd];
      const auto& point = xx[dd];
      const auto& delta = boundary_layer_[dd];
      if (point < left - delta) {
        // outside
        ret[0] = 0.0;
        break;
      } else if (point < left + delta) {
        // left boundary layer
        ret[0] *= phi_left((point - (left + delta)) / (2.0*delta));
      } else if (point < right - delta) {
        // inside
        // do nothing (keep value)
      } else if (point < right + delta) {
        // right boundary layer
        ret[0] *= phi_right((point - (right - delta)) / (2.0*delta));
      } else {
        // outside
        ret[0] = 0.0;
        break;
      }
    }
  } // ... evaluate(...)

private:
  void check_input() const
  {
    if (!(Common::FloatCmp::gt(upper_right_, lower_left_)))
      DUNE_THROW(Exceptions::wrong_input_given,
                 "upper_right has to be greater than lower_left!\n"
                 << "lower_left = [" << lower_left_ << "]\n"
                 << "upper_right = [" << upper_right_ << "]");
    if (!(Common::FloatCmp::gt(boundary_layer_, StuffDomainType(0))))
      DUNE_THROW(Exceptions::wrong_input_given,
                 "boundary_layer has to be strictly positive!\n"
                 << "boundary_layer = [" << boundary_layer_ << "]");
    if (Common::FloatCmp::gt(boundary_layer_*2.0, upper_right_ - lower_left_))
      DUNE_THROW(Exceptions::wrong_input_given,
                 "boundary_layer has to be thin enough!\n"
                 "2*boundary_layer = [" << boundary_layer_*2.0 << "]\n"
                 << "upper_right - lower_left = [" << upper_right_ - lower_left_ << "]");
  } // .. check_input(...)

  RangeFieldType phi_left(const RangeFieldType& point) const
  {
    if (point < -1.0)
      return 0.0;
    else if (point > 0.0)
      return 1.0;
    else
      return std::pow(1.0 + point, 2)*(1.0 - 2.0*point);
  } // ... phi_left(...)

  RangeFieldType phi_right(const RangeFieldType& point) const
  {
    if (point < 0.0)
      return 1.0;
    else if (point > 1.0)
      return 0.0;
    else
      return std::pow(1.0 - point, 2)*(1.0 + 2.0*point);
  } // ... phi_right(...)

  const StuffDomainType lower_left_;
  const StuffDomainType upper_right_;
  const StuffDomainType boundary_layer_;
  const StuffRangeType value_;
  const std::string name_;
}; // class FlatTop< ..., 1, 1 >

} // namespace Functions
} // namespace Stuff
} // namespace Dune

#endif // DUNE_STUFF_FUNCTIONS_FLATTOP_HH
<|endoftext|>