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

  Program:   Insight Segmentation & Registration Toolkit
  Module:    itkMultiThreaderTest.cxx
  Language:  C++
  Date:      $Date$
  Version:   $Revision$

  Copyright (c) Insight Software Consortium. All rights reserved.
  See ITKCopyright.txt or http://www.itk.org/HTML/Copyright.htm for details.

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

=========================================================================*/
#if defined(_MSC_VER)
#pragma warning ( disable : 4786 )
#endif

#include "itkConfigure.h"
#include "itkMultiThreader.h"

int itkMultiThreaderTest(int argc, char* argv[])
{
  // Choose a number of threads.
  int numberOfThreads = 10;
  if( argc > 1 )
    {
    const int nt = atoi( argv[1] );
    if(nt > 1)
      {
      numberOfThreads = nt;
      }
    }

  itk::MultiThreader::Pointer    threader = itk::MultiThreader::New();

  itk::MultiThreader::SetGlobalDefaultNumberOfThreads( numberOfThreads );

}

namespace itkMultiThreaderTestHelpers
{

void ThreadedMethod()
{

#ifdef ITK_USE_PTHREADS
// ThreadProcessIDType threadId = pthread_self();
#endif

#ifdef ITK_USE_WIN32_THREADS
// ThreadProcessIDType threadId = GetCurrentThread();
#endif

#ifdef ITK_USE_SPROC
// const ThreadProcessIDType threadId = GetCurrentThread()  ??;
#endif

}

} // end of itkMultiThreaderTestHelpers
<commit_msg>ENH: Adding default return value of EXIT_SUCCESS.<commit_after>/*=========================================================================

  Program:   Insight Segmentation & Registration Toolkit
  Module:    itkMultiThreaderTest.cxx
  Language:  C++
  Date:      $Date$
  Version:   $Revision$

  Copyright (c) Insight Software Consortium. All rights reserved.
  See ITKCopyright.txt or http://www.itk.org/HTML/Copyright.htm for details.

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

=========================================================================*/
#if defined(_MSC_VER)
#pragma warning ( disable : 4786 )
#endif

#include "itkConfigure.h"
#include "itkMultiThreader.h"

int itkMultiThreaderTest(int argc, char* argv[])
{
  // Choose a number of threads.
  int numberOfThreads = 10;
  if( argc > 1 )
    {
    const int nt = atoi( argv[1] );
    if(nt > 1)
      {
      numberOfThreads = nt;
      }
    }

  itk::MultiThreader::Pointer    threader = itk::MultiThreader::New();

  itk::MultiThreader::SetGlobalDefaultNumberOfThreads( numberOfThreads );

  return EXIT_SUCCESS;
}

namespace itkMultiThreaderTestHelpers
{

void ThreadedMethod()
{

#ifdef ITK_USE_PTHREADS
// ThreadProcessIDType threadId = pthread_self();
#endif

#ifdef ITK_USE_WIN32_THREADS
// ThreadProcessIDType threadId = GetCurrentThread();
#endif

#ifdef ITK_USE_SPROC
// const ThreadProcessIDType threadId = GetCurrentThread()  ??;
#endif

}

} // end of itkMultiThreaderTestHelpers
<|endoftext|>


<commit_before>/*
 * SnowPlow Arduino Tracker
 *
 * @description Arduino tracker for SnowPlow
 * @version     0.0.1
 * @author      Alex Dean
 * @copyright   SnowPlow Analytics Ltd
 * @license     Apache License Version 2.0
 *
 * Copyright (c) 2012 SnowPlow Analytics Ltd. All rights reserved.
 *
 * This program is licensed to you under the Apache License Version 2.0,
 * and you may not use this file except in compliance with the Apache License Version 2.0.
 * You may obtain a copy of the Apache License Version 2.0 at http://www.apache.org/licenses/LICENSE-2.0.
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the Apache License Version 2.0 is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the Apache License Version 2.0 for the specific language governing permissions and limitations there under.
 */

#include <stdlib.h>
#include <SPI.h>
#include "SnowPlowTracker.h"
#include <Ethernet.h>
#include <EthernetClient.h>

#define LOGGING

// Initialize constants
const String SnowPlowTracker::kUserAgent = "Arduino/2.0";
const String SnowPlowTracker::kVersion = "arduino-0.1.0";

/**
 * Constructor for SnowPlow class.
 *
 * @param aEthernet Pointer to the
 *        EthernetClass (initialised
 *        outside of this library)
 * @param aMac The MAC address of the
 *        Arduino's WiFi or Ethernet
 *        Shield
 * @param aAppId The SnowPlow application
 *        ID
 **/
SnowPlowTracker::SnowPlowTracker(EthernetClass *aEthernet, const byte* aMac, const String aAppId) {
  this->ethernet = aEthernet;
  this->mac = (byte*)aMac;
  this->appId = aAppId;
}

/**
 * Initializes the SnowPlow tracker to
 * talk to a collector hosted on
 * CloudFront.
 *
 * @param aCfSubdomain The subdomain
 *        of the CloudFront collector
 *        e.g. "d3rkrsqgmqf"
 */
void SnowPlowTracker::initCf(const String aCfSubdomain) {
  const String host = aCfSubdomain + String(".cloudfront.net");
  this->init(host);
}

/**
 * Initializes the SnowPlow tracker
 * to speak to a URL-based (self-
 * hosted) collector.
 *
 * @param aHost The hostname of the
 *        URL hosting the collector
 *        e.g. tracking.mysite.com
 */
void SnowPlowTracker::initUrl(const String aHost) {
  this->init(aHost);
}

/**
 * Sets the User Id for this Arduino.
 * Overrides the default User Id, which
 * is the Arduino's MAC address.
 *
 * @param @aUserId The new User Id
 */
void SnowPlowTracker::setUserId(String aUserId) {
  this->userId = aUserId;

#ifdef LOGGING
  Serial.print("SnowPlow User Id updated to: ");
  Serial.println(this->userId);
#endif
}

/**
 * Tracks a structured event to a
 * SnowPlow collector: version
 * where the value field is an int.
 *
 * @param aCategory The name you supply for
 *        the group of objects you want to track
 * @param aAction A string that is uniquely
 *        paired with each category, and commonly
 *        used to define the type of user
 *        interaction for the web object
 * @param aLabel An optional string
 *        to provide additional dimensions to the
 *        event data
 * @param aProperty An optional string
 *        describing the object or the action
 *        performed on it. This might be the
 *        quantity of an item added to basket
 * @param aValue An integer value that
 *        you can use to provide numerical data
 *        about the user event
 * @return An integer indicating the success/failure
 *         of logging the event to SnowPlow
 */
int SnowPlowTracker::trackEvent(
  const String aCategory,
  const String aAction,
  const String aLabel,
  const String aProperty,
  const int aValue) const {

  // Cast aValue to String and call appropriate trackEvent
  trackEvent(aCategory, aAction, aLabel, aProperty, String(aValue));
}

/**
 * Tracks a structured event to a
 * SnowPlow collector: version
 * where the value field is a float.
 *
 * @param aCategory The name you supply for
 *        the group of objects you want to track
 * @param aAction A string that is uniquely
 *        paired with each category, and commonly
 *        used to define the type of user
 *        interaction for the web object
 * @param aLabel An optional string
 *        to provide additional dimensions to the
 *        event data
 * @param aProperty An optional string
 *        describing the object or the action
 *        performed on it. This might be the
 *        quantity of an item added to basket
 * @param aValue A double value that
 *        you can use to provide numerical data
 *        about the user event
 * @param aValuePrecision How many digits to keep
 *        after the decimal sign
 * @return An integer indicating the success/failure
 *         of logging the event to SnowPlow
 */
int SnowPlowTracker::trackEvent(
  const String aCategory,
  const String aAction,
  const String aLabel,
  const String aProperty,
  const double aValue,
  const int aValuePrecision) const {

  // Cast aValue to String and call appropriate trackEvent
  trackEvent(aCategory, aAction, aLabel, aProperty, double2String(aValue, aValuePrecision));
}

/**
 * Tracks a structured event to a
 * SnowPlow collector: version
 * where the value field is a float.
 *
 * @param aCategory The name you supply for
 *        the group of objects you want to track
 * @param aAction A string that is uniquely
 *        paired with each category, and commonly
 *        used to define the type of user
 *        interaction for the web object
 * @param aLabel An optional string
 *        to provide additional dimensions to the
 *        event data
 * @param aProperty An optional string
 *        describing the object or the action
 *        performed on it. This might be the
 *        quantity of an item added to basket
 * @param aValue A float value that
 *        you can use to provide numerical data
 *        about the user event
 * @param aValuePrecision How many digits to keep
 *        after the decimal sign
 * @return An integer indicating the success/failure
 *         of logging the event to SnowPlow
 */
int SnowPlowTracker::trackEvent(
  const String aCategory,
  const String aAction,
  const String aLabel,
  const String aProperty,
  const float aValue,
  const int aValuePrecision) const {

  // Cast aValue to String and call appropriate trackEvent
  trackEvent(aCategory, aAction, aLabel, aProperty, double2String(aValue, aValuePrecision));
}

/**
 * Tracks a structured event to a
 * SnowPlow collector: version
 * where the value field is a String.
 *
 * @param aCategory The name you supply for
 *        the group of objects you want to track
 * @param aAction A string that is uniquely
 *        paired with each category, and commonly
 *        used to define the type of user
 *        interaction for the web object
 * @param aLabel An optional string
 *        to provide additional dimensions to the
 *        event data
 * @param aProperty An optional string
 *        describing the object or the action
 *        performed on it. This might be the
 *        quantity of an item added to basket
 * @param aValue A String value that
 *        you can use to provide non-numerical data
 *        about the user event
 * @return An integer indicating the success/failure
 *         of logging the event to SnowPlow
 */
int SnowPlowTracker::trackEvent(
  const String aCategory,
  const String aAction,
  const String aLabel,
  const String aProperty,
  const String aValue) const {

#ifdef LOGGING
  Serial.println("Tracking event!");
#endif

  return SnowPlowTracker::SUCCESS;
}

/**
 * Common initialization, called by
 * both initCf and initUrl.
 *
 * @param aHost The hostname of the
 *        URL hosting the collector
 *        e.g. tracking.mysite.com
 *        or d3rkrsqgmqf.cloudfront.net
 */
void SnowPlowTracker::init(const String aHost) {

  // Set collectorHost and userId
  this->collectorHost = aHost;
  this->userId = mac2String(this->mac);

  // Boot the Ethernet connection
  this->ethernet->begin((byte*)this->mac);
  delay(1000); // Wait 1 sec
  this->client = new EthernetClient();

#ifdef LOGGING
  Serial.print("SnowPlowTracker initialized with collector host: ");
  Serial.println(this->collectorHost);
#endif
}

/**
 * Converts a MAC address byte array
 * into a String. Generated String is
 * of the format: "00:01:0A:2E:05:0B"
 *
 * @param aMac The MAC address, in bytes,
 *             to convert
 * @return the MAC address as a String
 */
String SnowPlowTracker::mac2String(const byte* aMac) {
  const int macLength = 6;
  String buffer = String();
  for (int i = 0; i < macLength; i++) {
    buffer += String(aMac[i], HEX);
    if (i < macLength - 1) {
      buffer += ":";
    }
  }
  return buffer;
}

/**
 * Converts a double (or a float)
 * into a String. Generated String is
 * 1 or more characters long, with the
 * number of digits after the decimal
 * point specified by `aPrecision`.
 *
 * @param aDbl The double (or float) to
 *        convert into a String
 * @return the converted String
 */
String SnowPlowTracker::double2String(const double aDouble, const int aPrecision) {
  char buffer[25];
  dtostrf(aDouble, 1, aPrecision, buffer);
  return String(buffer);
}

/*

int SnowPlowTracker::trackEvent(const String category, const String action, const String label, const String property, const float value) const {
  // TODO: fix this crap.
  char rxdata[150];
  int ret = 0;
  int stringPos = 0;
  boolean DataRx = false;
  boolean RxLoop = true;
  char c;
  unsigned long timeout_time = 0;
  unsigned long time_now = 0;
  unsigned long timeout = 3000; // 3 seconds
  String myDataString = ""; // Allocate for actual data sent

  if (client->connect(serverName,80)) {
    if (client->connected()) {

      client->println("GET /i HTTP/1.1");

      client->print("Host: ");
      client->println(this->collectorUrl);

      client->print("User-Agent: ");
      client->println(kUserAgent);

      client->println();

      // TODO: check if we need more headers.

      // Read from the nic
      //
      timeout_time = millis()+ timeout;
      while ((timeout_time > time_now) && RxLoop) {
        if (client->available()) {
          if (!DataRx)
            DataRx= true;
          c = client->read();
          rxdata[stringPos] = c;
          stringPos += 1;
        } else {
          rxdata[stringPos] = 0;

          if (DataRx) {
            DataRx= false;
            RxLoop = false;

            ret=1;
          }
        }//else
        time_now = millis();
      }// while ((timeout_time > time_now) && RxLoop) {

      client->stop();
    }
  }// if (client->connect(serverName,80)) {

  // Return updated status code
  return ret;
}

*/<commit_msg>Doco tweak<commit_after>/*
 * SnowPlow Arduino Tracker
 *
 * @description Arduino tracker for SnowPlow
 * @version     0.0.1
 * @author      Alex Dean
 * @copyright   SnowPlow Analytics Ltd
 * @license     Apache License Version 2.0
 *
 * Copyright (c) 2012 SnowPlow Analytics Ltd. All rights reserved.
 *
 * This program is licensed to you under the Apache License Version 2.0,
 * and you may not use this file except in compliance with the Apache License Version 2.0.
 * You may obtain a copy of the Apache License Version 2.0 at http://www.apache.org/licenses/LICENSE-2.0.
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the Apache License Version 2.0 is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the Apache License Version 2.0 for the specific language governing permissions and limitations there under.
 */

#include <stdlib.h>
#include <SPI.h>
#include "SnowPlowTracker.h"
#include <Ethernet.h>
#include <EthernetClient.h>

#define LOGGING

// Initialize constants
const String SnowPlowTracker::kUserAgent = "Arduino/2.0";
const String SnowPlowTracker::kVersion = "arduino-0.1.0";

/**
 * Constructor for the SnowPlowTracker
 * class.
 *
 * @param aEthernet Pointer to the
 *        EthernetClass (initialised
 *        outside of this library)
 * @param aMac The MAC address of the
 *        Arduino's WiFi or Ethernet
 *        Shield
 * @param aAppId The SnowPlow application
 *        ID
 **/
SnowPlowTracker::SnowPlowTracker(EthernetClass *aEthernet, const byte* aMac, const String aAppId) {
  this->ethernet = aEthernet;
  this->mac = (byte*)aMac;
  this->appId = aAppId;
}

/**
 * Initializes the SnowPlow tracker to
 * talk to a collector hosted on
 * CloudFront.
 *
 * @param aCfSubdomain The subdomain
 *        of the CloudFront collector
 *        e.g. "d3rkrsqgmqf"
 */
void SnowPlowTracker::initCf(const String aCfSubdomain) {
  const String host = aCfSubdomain + String(".cloudfront.net");
  this->init(host);
}

/**
 * Initializes the SnowPlow tracker
 * to speak to a URL-based (self-
 * hosted) collector.
 *
 * @param aHost The hostname of the
 *        URL hosting the collector
 *        e.g. tracking.mysite.com
 */
void SnowPlowTracker::initUrl(const String aHost) {
  this->init(aHost);
}

/**
 * Sets the User Id for this Arduino.
 * Overrides the default User Id, which
 * is the Arduino's MAC address.
 *
 * @param @aUserId The new User Id
 */
void SnowPlowTracker::setUserId(String aUserId) {
  this->userId = aUserId;

#ifdef LOGGING
  Serial.print("SnowPlow User Id updated to: ");
  Serial.println(this->userId);
#endif
}

/**
 * Tracks a structured event to a
 * SnowPlow collector: version
 * where the value field is an int.
 *
 * @param aCategory The name you supply for
 *        the group of objects you want to track
 * @param aAction A string that is uniquely
 *        paired with each category, and commonly
 *        used to define the type of user
 *        interaction for the web object
 * @param aLabel An optional string
 *        to provide additional dimensions to the
 *        event data
 * @param aProperty An optional string
 *        describing the object or the action
 *        performed on it. This might be the
 *        quantity of an item added to basket
 * @param aValue An integer value that
 *        you can use to provide numerical data
 *        about the user event
 * @return An integer indicating the success/failure
 *         of logging the event to SnowPlow
 */
int SnowPlowTracker::trackEvent(
  const String aCategory,
  const String aAction,
  const String aLabel,
  const String aProperty,
  const int aValue) const {

  // Cast aValue to String and call appropriate trackEvent
  trackEvent(aCategory, aAction, aLabel, aProperty, String(aValue));
}

/**
 * Tracks a structured event to a
 * SnowPlow collector: version
 * where the value field is a float.
 *
 * @param aCategory The name you supply for
 *        the group of objects you want to track
 * @param aAction A string that is uniquely
 *        paired with each category, and commonly
 *        used to define the type of user
 *        interaction for the web object
 * @param aLabel An optional string
 *        to provide additional dimensions to the
 *        event data
 * @param aProperty An optional string
 *        describing the object or the action
 *        performed on it. This might be the
 *        quantity of an item added to basket
 * @param aValue A double value that
 *        you can use to provide numerical data
 *        about the user event
 * @param aValuePrecision How many digits to keep
 *        after the decimal sign
 * @return An integer indicating the success/failure
 *         of logging the event to SnowPlow
 */
int SnowPlowTracker::trackEvent(
  const String aCategory,
  const String aAction,
  const String aLabel,
  const String aProperty,
  const double aValue,
  const int aValuePrecision) const {

  // Cast aValue to String and call appropriate trackEvent
  trackEvent(aCategory, aAction, aLabel, aProperty, double2String(aValue, aValuePrecision));
}

/**
 * Tracks a structured event to a
 * SnowPlow collector: version
 * where the value field is a float.
 *
 * @param aCategory The name you supply for
 *        the group of objects you want to track
 * @param aAction A string that is uniquely
 *        paired with each category, and commonly
 *        used to define the type of user
 *        interaction for the web object
 * @param aLabel An optional string
 *        to provide additional dimensions to the
 *        event data
 * @param aProperty An optional string
 *        describing the object or the action
 *        performed on it. This might be the
 *        quantity of an item added to basket
 * @param aValue A float value that
 *        you can use to provide numerical data
 *        about the user event
 * @param aValuePrecision How many digits to keep
 *        after the decimal sign
 * @return An integer indicating the success/failure
 *         of logging the event to SnowPlow
 */
int SnowPlowTracker::trackEvent(
  const String aCategory,
  const String aAction,
  const String aLabel,
  const String aProperty,
  const float aValue,
  const int aValuePrecision) const {

  // Cast aValue to String and call appropriate trackEvent
  trackEvent(aCategory, aAction, aLabel, aProperty, double2String(aValue, aValuePrecision));
}

/**
 * Tracks a structured event to a
 * SnowPlow collector: version
 * where the value field is a String.
 *
 * @param aCategory The name you supply for
 *        the group of objects you want to track
 * @param aAction A string that is uniquely
 *        paired with each category, and commonly
 *        used to define the type of user
 *        interaction for the web object
 * @param aLabel An optional string
 *        to provide additional dimensions to the
 *        event data
 * @param aProperty An optional string
 *        describing the object or the action
 *        performed on it. This might be the
 *        quantity of an item added to basket
 * @param aValue A String value that
 *        you can use to provide non-numerical data
 *        about the user event
 * @return An integer indicating the success/failure
 *         of logging the event to SnowPlow
 */
int SnowPlowTracker::trackEvent(
  const String aCategory,
  const String aAction,
  const String aLabel,
  const String aProperty,
  const String aValue) const {

#ifdef LOGGING
  Serial.println("Tracking event!");
#endif

  return SnowPlowTracker::SUCCESS;
}

/**
 * Common initialization, called by
 * both initCf and initUrl.
 *
 * @param aHost The hostname of the
 *        URL hosting the collector
 *        e.g. tracking.mysite.com
 *        or d3rkrsqgmqf.cloudfront.net
 */
void SnowPlowTracker::init(const String aHost) {

  // Set collectorHost and userId
  this->collectorHost = aHost;
  this->userId = mac2String(this->mac);

  // Boot the Ethernet connection
  this->ethernet->begin((byte*)this->mac);
  delay(1000); // Wait 1 sec
  this->client = new EthernetClient();

#ifdef LOGGING
  Serial.print("SnowPlowTracker initialized with collector host: ");
  Serial.println(this->collectorHost);
#endif
}

/**
 * Converts a MAC address byte array
 * into a String. Generated String is
 * of the format: "00:01:0A:2E:05:0B"
 *
 * @param aMac The MAC address, in bytes,
 *             to convert
 * @return the MAC address as a String
 */
String SnowPlowTracker::mac2String(const byte* aMac) {
  const int macLength = 6;
  String buffer = String();
  for (int i = 0; i < macLength; i++) {
    buffer += String(aMac[i], HEX);
    if (i < macLength - 1) {
      buffer += ":";
    }
  }
  return buffer;
}

/**
 * Converts a double (or a float)
 * into a String. Generated String is
 * 1 or more characters long, with the
 * number of digits after the decimal
 * point specified by `aPrecision`.
 *
 * @param aDbl The double (or float) to
 *        convert into a String
 * @return the converted String
 */
String SnowPlowTracker::double2String(const double aDouble, const int aPrecision) {
  char buffer[25];
  dtostrf(aDouble, 1, aPrecision, buffer);
  return String(buffer);
}

/*

int SnowPlowTracker::trackEvent(const String category, const String action, const String label, const String property, const float value) const {
  // TODO: fix this crap.
  char rxdata[150];
  int ret = 0;
  int stringPos = 0;
  boolean DataRx = false;
  boolean RxLoop = true;
  char c;
  unsigned long timeout_time = 0;
  unsigned long time_now = 0;
  unsigned long timeout = 3000; // 3 seconds
  String myDataString = ""; // Allocate for actual data sent

  if (client->connect(serverName,80)) {
    if (client->connected()) {

      client->println("GET /i HTTP/1.1");

      client->print("Host: ");
      client->println(this->collectorUrl);

      client->print("User-Agent: ");
      client->println(kUserAgent);

      client->println();

      // TODO: check if we need more headers.

      // Read from the nic
      //
      timeout_time = millis()+ timeout;
      while ((timeout_time > time_now) && RxLoop) {
        if (client->available()) {
          if (!DataRx)
            DataRx= true;
          c = client->read();
          rxdata[stringPos] = c;
          stringPos += 1;
        } else {
          rxdata[stringPos] = 0;

          if (DataRx) {
            DataRx= false;
            RxLoop = false;

            ret=1;
          }
        }//else
        time_now = millis();
      }// while ((timeout_time > time_now) && RxLoop) {

      client->stop();
    }
  }// if (client->connect(serverName,80)) {

  // Return updated status code
  return ret;
}

*/
<|endoftext|>


<commit_before>
//
// This source file is part of appleseed.
// Visit http://appleseedhq.net/ for additional information and resources.
//
// This software is released under the MIT license.
//
// Copyright (c) 2010-2013 Francois Beaune, Jupiter Jazz Limited
// Copyright (c) 2014-2017 Francois Beaune, The appleseedhq Organization
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
//

// Interface header.
#include "adaptivepixelrenderer.h"

// appleseed.renderer headers.
#include "renderer/global/globallogger.h"
#include "renderer/global/globaltypes.h"
#include "renderer/kernel/aov/aovsettings.h"
#include "renderer/kernel/aov/imagestack.h"
#include "renderer/kernel/aov/tilestack.h"
#include "renderer/kernel/rendering/final/variationtracker.h"
#include "renderer/kernel/rendering/isamplerenderer.h"
#include "renderer/kernel/rendering/pixelcontext.h"
#include "renderer/kernel/rendering/pixelrendererbase.h"
#include "renderer/kernel/rendering/shadingresultframebuffer.h"
#include "renderer/kernel/shading/shadingfragment.h"
#include "renderer/kernel/shading/shadingresult.h"
#include "renderer/modeling/frame/frame.h"
#include "renderer/utility/settingsparsing.h"

// appleseed.foundation headers.
#include "foundation/image/color.h"
#include "foundation/image/image.h"
#include "foundation/image/tile.h"
#include "foundation/math/aabb.h"
#include "foundation/math/hash.h"
#include "foundation/math/minmax.h"
#include "foundation/math/scalar.h"
#include "foundation/math/vector.h"
#include "foundation/platform/types.h"
#include "foundation/utility/autoreleaseptr.h"
#include "foundation/utility/containers/dictionary.h"
#include "foundation/utility/statistics.h"

// Standard headers.
#include <algorithm>
#include <cassert>
#include <cmath>
#include <memory>

using namespace foundation;
using namespace std;

namespace renderer
{

namespace
{
    //
    // Adaptive pixel renderer.
    //

    class AdaptivePixelRenderer
      : public PixelRendererBase
    {
      public:
        AdaptivePixelRenderer(
            const Frame&                frame,
            ISampleRendererFactory*     factory,
            const ParamArray&           params,
            const size_t                thread_index)
          : m_params(params)
          , m_sample_renderer(factory->create(thread_index))
        {
            if (m_params.m_diagnostics)
            {
                ImageStack& images = frame.aov_images();

                m_variation_aov_index = images.get_index("variation");
                if (m_variation_aov_index == size_t(~0) && images.size() < MaxAOVCount)
                    m_variation_aov_index = images.append("variation", ImageStack::IdentificationType, 4, PixelFormatFloat);

                m_samples_aov_index = images.get_index("samples");
                if (m_samples_aov_index == size_t(~0) && images.size() < MaxAOVCount)
                    m_samples_aov_index = images.append("samples", ImageStack::IdentificationType, 4, PixelFormatFloat);

                if ((thread_index == 0) && (m_variation_aov_index == size_t(~0) || m_samples_aov_index == size_t(~0)))
                {
                    RENDERER_LOG_WARNING(
                        "could not create some of the diagnostic AOVs, maximum number of AOVs (" FMT_SIZE_T ") reached.",
                        MaxAOVCount);
                }
            }
        }

        virtual void release() APPLESEED_OVERRIDE
        {
            delete this;
        }

        virtual void on_tile_begin(
            const Frame&                frame,
            Tile&                       tile,
            TileStack&                  aov_tiles) APPLESEED_OVERRIDE
        {
            m_scratch_fb_half_width = truncate<int>(ceil(frame.get_filter().get_xradius()));
            m_scratch_fb_half_height = truncate<int>(ceil(frame.get_filter().get_yradius()));

            m_scratch_fb.reset(
                new ShadingResultFrameBuffer(
                    2 * m_scratch_fb_half_width + 1,
                    2 * m_scratch_fb_half_height + 1,
                    frame.aov_images().size(),
                    frame.get_filter()));

            if (m_params.m_diagnostics)
                m_diagnostics.reset(new Tile(tile.get_width(), tile.get_height(), 2, PixelFormatFloat));
        }

        virtual void on_tile_end(
            const Frame&                frame,
            Tile&                       tile,
            TileStack&                  aov_tiles) APPLESEED_OVERRIDE
        {
            if (m_params.m_diagnostics)
            {
                const size_t width = tile.get_width();
                const size_t height = tile.get_height();

                for (size_t y = 0; y < height; ++y)
                {
                    for (size_t x = 0; x < width; ++x)
                    {
                        Color<float, 2> values;
                        m_diagnostics->get_pixel(x, y, values);

                        if (m_variation_aov_index != size_t(~0))
                            aov_tiles.set_pixel(x, y, m_variation_aov_index, scalar_to_color(values[0]));

                        if (m_samples_aov_index != size_t(~0))
                            aov_tiles.set_pixel(x, y, m_samples_aov_index, scalar_to_color(values[1]));
                    }
                }
            }
        }

        virtual void render_pixel(
            const Frame&                frame,
            Tile&                       tile,
            TileStack&                  aov_tiles,
            const AABB2i&               tile_bbox,
            const size_t                pass_hash,
            const Vector2i&             pi,
            const Vector2i&             pt,
            SamplingContext::RNGType&   rng,
            ShadingResultFrameBuffer&   framebuffer) APPLESEED_OVERRIDE
        {
            const size_t aov_count = frame.aov_images().size();

            on_pixel_begin();

            m_scratch_fb->clear();

            // Create a sampling context.
            const size_t frame_width = frame.image().properties().m_canvas_width;
            const size_t instance =
                mix_uint32(
                    static_cast<uint32>(pass_hash),
                    static_cast<uint32>(pi.y * frame_width + pi.x));
            SamplingContext sampling_context(
                rng,
                m_params.m_sampling_mode,
                2,                          // number of dimensions
                0,                          // number of samples -- unknown
                instance);                  // initial instance number

            VariationTracker trackers[3];

            while (true)
            {
                trackers[0].reset_variation();
                trackers[1].reset_variation();
                trackers[2].reset_variation();

                // Don't exceed 'max' samples in total.
                assert(trackers[0].get_size() <= m_params.m_max_samples);
                const size_t remaining_samples = m_params.m_max_samples - trackers[0].get_size();
                if (remaining_samples == 0)
                    break;

                // Each batch contains 'min' samples.
                const size_t batch_size = min(m_params.m_min_samples, remaining_samples);

                for (size_t i = 0; i < batch_size; ++i)
                {
                    // Generate a uniform sample in [0,1)^2.
                    const Vector2d s = sampling_context.next2<Vector2d>();

                    // Compute the sample position in NDC.
                    const Vector2d sample_position = frame.get_sample_position(pi.x + s.x, pi.y + s.y);

                    // Create a pixel context that identifies the pixel and sample currently being rendered.
                    const PixelContext pixel_context(pi, sample_position);

                    // Render the sample.
                    ShadingResult shading_result(aov_count);
                    SamplingContext child_sampling_context(sampling_context);
                    m_sample_renderer->render_sample(
                        child_sampling_context,
                        pixel_context,
                        sample_position,
                        shading_result);

                    // Ignore invalid samples.
                    if (!shading_result.is_valid_linear_rgb())
                    {
                        signal_invalid_sample();
                        continue;
                    }

                    // Merge the sample into the scratch framebuffer.
                    m_scratch_fb->add(
                        static_cast<float>(m_scratch_fb_half_width + s.x),
                        static_cast<float>(m_scratch_fb_half_height + s.y),
                        shading_result);

                    // Update statistics for this pixel.
                    // todo: variation should be computed in a user-selectable color space, typically the target color space.
                    // todo: one tracker per AOV?
                    trackers[0].insert(shading_result.m_main.m_color[0]);
                    trackers[1].insert(shading_result.m_main.m_color[1]);
                    trackers[2].insert(shading_result.m_main.m_color[2]);
                }

                // Stop if the variation criterion is met.
                if (trackers[0].get_variation() <= m_params.m_max_variation &&
                    trackers[1].get_variation() <= m_params.m_max_variation &&
                    trackers[2].get_variation() <= m_params.m_max_variation)
                    break;
            }

            // Merge the scratch framebuffer into the output framebuffer.
            const float rcp_sample_count = 1.0f / trackers[0].get_size();
            for (int y = -m_scratch_fb_half_height; y <= m_scratch_fb_half_height; ++y)
            {
                for (int x = -m_scratch_fb_half_width; x <= m_scratch_fb_half_width; ++x)
                {
                    if (tile_bbox.contains(Vector2i(pt.x + x, pt.y + y)))
                    {
                        framebuffer.merge(                  // destination
                            pt.x + x,                       // destination X
                            pt.y + y,                       // destination Y
                            *m_scratch_fb.get(),            // source
                            m_scratch_fb_half_width + x,    // source X
                            m_scratch_fb_half_height + y,   // source Y
                            rcp_sample_count);              // scaling
                    }
                }
            }

            // Store diagnostics values in the diagnostics tile.
            if (m_params.m_diagnostics && tile_bbox.contains(pt))
            {
                Color<float, 2> values;

                values[0] =
                    saturate(
                        max(
                            trackers[0].get_variation(),
                            trackers[1].get_variation(),
                            trackers[2].get_variation())
                        / m_params.m_max_variation);

                values[1] =
                    m_params.m_min_samples == m_params.m_max_samples
                        ? 1.0f
                        : fit(
                            static_cast<float>(trackers[0].get_size()),
                            static_cast<float>(m_params.m_min_samples),
                            static_cast<float>(m_params.m_max_samples),
                            0.0f, 1.0f);

                m_diagnostics->set_pixel(pt.x, pt.y, values);
            }

            on_pixel_end(pi);
        }

        virtual StatisticsVector get_statistics() const APPLESEED_OVERRIDE
        {
            return m_sample_renderer->get_statistics();
        }

      private:
        struct Parameters
        {
            const SamplingContext::Mode     m_sampling_mode;
            const size_t                    m_min_samples;
            const size_t                    m_max_samples;
            const float                     m_max_variation;
            const bool                      m_diagnostics;

            explicit Parameters(const ParamArray& params)
              : m_sampling_mode(get_sampling_context_mode(params))
              , m_min_samples(params.get_required<size_t>("min_samples", 16))
              , m_max_samples(params.get_required<size_t>("max_samples", 256))
              , m_max_variation(pow(10.0f, -params.get_optional<float>("quality", 2.0f)))
              , m_diagnostics(params.get_optional<bool>("enable_diagnostics", false))
            {
            }
        };

        const Parameters                    m_params;
        auto_release_ptr<ISampleRenderer>   m_sample_renderer;
        size_t                              m_variation_aov_index;
        size_t                              m_samples_aov_index;
        int                                 m_scratch_fb_half_width;
        int                                 m_scratch_fb_half_height;
        auto_ptr<ShadingResultFrameBuffer>  m_scratch_fb;
        auto_ptr<Tile>                      m_diagnostics;

        static Color4f scalar_to_color(const float value)
        {
            static const Color4f Blue(0.0f, 0.0f, 1.0f, 1.0f);
            static const Color4f Red(1.0f, 0.0f, 0.0f, 1.0f);
            return lerp(Blue, Red, saturate(value));
        }
    };
}

//
// AdaptivePixelRendererFactory class implementation.
//

AdaptivePixelRendererFactory::AdaptivePixelRendererFactory(
    const Frame&                frame,
    ISampleRendererFactory*     factory,
    const ParamArray&           params)
  : m_frame(frame)
  , m_factory(factory)
  , m_params(params)
{
}

void AdaptivePixelRendererFactory::release()
{
    delete this;
}

IPixelRenderer* AdaptivePixelRendererFactory::create(
    const size_t                thread_index)
{
    return new AdaptivePixelRenderer(
        m_frame,
        m_factory,
        m_params,
        thread_index);
}

Dictionary AdaptivePixelRendererFactory::get_params_metadata()
{
    Dictionary metadata;

    metadata.dictionaries().insert(
        "min_samples",
        Dictionary()
            .insert("type", "int")
            .insert("default", "16")
            .insert("label", "Min Samples")
            .insert("help", "Minimum number of anti-aliasing samples"));

    metadata.dictionaries().insert(
        "max_samples",
        Dictionary()
            .insert("type", "int")
            .insert("default", "256")
            .insert("label", "Max Samples")
            .insert("help", "Maximum number of anti-aliasing samples"));

    metadata.dictionaries().insert(
        "quality",
        Dictionary()
            .insert("type", "float")
            .insert("default", "2.0")
            .insert("label", "Quality")
            .insert("help", "Quality factor"));

    metadata.dictionaries().insert(
        "enable_diagnostics",
        Dictionary()
            .insert("type", "bool")
            .insert("default", "false")
            .insert("label", "Enable Diagnostics")
            .insert(
                "help",
                "Enable adaptive sampling diagnostics"));

    return metadata;
}

}   // namespace renderer
<commit_msg>Do not create aov images directly.<commit_after>
//
// This source file is part of appleseed.
// Visit http://appleseedhq.net/ for additional information and resources.
//
// This software is released under the MIT license.
//
// Copyright (c) 2010-2013 Francois Beaune, Jupiter Jazz Limited
// Copyright (c) 2014-2017 Francois Beaune, The appleseedhq Organization
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
//

// Interface header.
#include "adaptivepixelrenderer.h"

// appleseed.renderer headers.
#include "renderer/global/globallogger.h"
#include "renderer/global/globaltypes.h"
#include "renderer/kernel/aov/aovsettings.h"
#include "renderer/kernel/aov/imagestack.h"
#include "renderer/kernel/aov/tilestack.h"
#include "renderer/kernel/rendering/final/variationtracker.h"
#include "renderer/kernel/rendering/isamplerenderer.h"
#include "renderer/kernel/rendering/pixelcontext.h"
#include "renderer/kernel/rendering/pixelrendererbase.h"
#include "renderer/kernel/rendering/shadingresultframebuffer.h"
#include "renderer/kernel/shading/shadingfragment.h"
#include "renderer/kernel/shading/shadingresult.h"
#include "renderer/modeling/frame/frame.h"
#include "renderer/utility/settingsparsing.h"

// appleseed.foundation headers.
#include "foundation/image/color.h"
#include "foundation/image/image.h"
#include "foundation/image/tile.h"
#include "foundation/math/aabb.h"
#include "foundation/math/hash.h"
#include "foundation/math/minmax.h"
#include "foundation/math/scalar.h"
#include "foundation/math/vector.h"
#include "foundation/platform/types.h"
#include "foundation/utility/autoreleaseptr.h"
#include "foundation/utility/containers/dictionary.h"
#include "foundation/utility/statistics.h"

// Standard headers.
#include <algorithm>
#include <cassert>
#include <cmath>
#include <memory>

using namespace foundation;
using namespace std;

namespace renderer
{

namespace
{
    //
    // Adaptive pixel renderer.
    //

    class AdaptivePixelRenderer
      : public PixelRendererBase
    {
      public:
        AdaptivePixelRenderer(
            const Frame&                frame,
            ISampleRendererFactory*     factory,
            const ParamArray&           params,
            const size_t                thread_index)
          : m_params(params)
          , m_sample_renderer(factory->create(thread_index))
        {
            if (m_params.m_diagnostics)
            {
                m_variation_aov_index = frame.create_extra_aov_image("variation");
                m_samples_aov_index = frame.create_extra_aov_image("samples");

                if ((thread_index == 0) && (m_variation_aov_index == size_t(~0) || m_samples_aov_index == size_t(~0)))
                {
                    RENDERER_LOG_WARNING(
                        "could not create some of the diagnostic AOVs, maximum number of AOVs (" FMT_SIZE_T ") reached.",
                        MaxAOVCount);
                }
            }
        }

        virtual void release() APPLESEED_OVERRIDE
        {
            delete this;
        }

        virtual void on_tile_begin(
            const Frame&                frame,
            Tile&                       tile,
            TileStack&                  aov_tiles) APPLESEED_OVERRIDE
        {
            m_scratch_fb_half_width = truncate<int>(ceil(frame.get_filter().get_xradius()));
            m_scratch_fb_half_height = truncate<int>(ceil(frame.get_filter().get_yradius()));

            m_scratch_fb.reset(
                new ShadingResultFrameBuffer(
                    2 * m_scratch_fb_half_width + 1,
                    2 * m_scratch_fb_half_height + 1,
                    frame.aov_images().size(),
                    frame.get_filter()));

            if (m_params.m_diagnostics)
                m_diagnostics.reset(new Tile(tile.get_width(), tile.get_height(), 2, PixelFormatFloat));
        }

        virtual void on_tile_end(
            const Frame&                frame,
            Tile&                       tile,
            TileStack&                  aov_tiles) APPLESEED_OVERRIDE
        {
            if (m_params.m_diagnostics)
            {
                const size_t width = tile.get_width();
                const size_t height = tile.get_height();

                for (size_t y = 0; y < height; ++y)
                {
                    for (size_t x = 0; x < width; ++x)
                    {
                        Color<float, 2> values;
                        m_diagnostics->get_pixel(x, y, values);

                        if (m_variation_aov_index != size_t(~0))
                            aov_tiles.set_pixel(x, y, m_variation_aov_index, scalar_to_color(values[0]));

                        if (m_samples_aov_index != size_t(~0))
                            aov_tiles.set_pixel(x, y, m_samples_aov_index, scalar_to_color(values[1]));
                    }
                }
            }
        }

        virtual void render_pixel(
            const Frame&                frame,
            Tile&                       tile,
            TileStack&                  aov_tiles,
            const AABB2i&               tile_bbox,
            const size_t                pass_hash,
            const Vector2i&             pi,
            const Vector2i&             pt,
            SamplingContext::RNGType&   rng,
            ShadingResultFrameBuffer&   framebuffer) APPLESEED_OVERRIDE
        {
            const size_t aov_count = frame.aov_images().size();

            on_pixel_begin();

            m_scratch_fb->clear();

            // Create a sampling context.
            const size_t frame_width = frame.image().properties().m_canvas_width;
            const size_t instance =
                mix_uint32(
                    static_cast<uint32>(pass_hash),
                    static_cast<uint32>(pi.y * frame_width + pi.x));
            SamplingContext sampling_context(
                rng,
                m_params.m_sampling_mode,
                2,                          // number of dimensions
                0,                          // number of samples -- unknown
                instance);                  // initial instance number

            VariationTracker trackers[3];

            while (true)
            {
                trackers[0].reset_variation();
                trackers[1].reset_variation();
                trackers[2].reset_variation();

                // Don't exceed 'max' samples in total.
                assert(trackers[0].get_size() <= m_params.m_max_samples);
                const size_t remaining_samples = m_params.m_max_samples - trackers[0].get_size();
                if (remaining_samples == 0)
                    break;

                // Each batch contains 'min' samples.
                const size_t batch_size = min(m_params.m_min_samples, remaining_samples);

                for (size_t i = 0; i < batch_size; ++i)
                {
                    // Generate a uniform sample in [0,1)^2.
                    const Vector2d s = sampling_context.next2<Vector2d>();

                    // Compute the sample position in NDC.
                    const Vector2d sample_position = frame.get_sample_position(pi.x + s.x, pi.y + s.y);

                    // Create a pixel context that identifies the pixel and sample currently being rendered.
                    const PixelContext pixel_context(pi, sample_position);

                    // Render the sample.
                    ShadingResult shading_result(aov_count);
                    SamplingContext child_sampling_context(sampling_context);
                    m_sample_renderer->render_sample(
                        child_sampling_context,
                        pixel_context,
                        sample_position,
                        shading_result);

                    // Ignore invalid samples.
                    if (!shading_result.is_valid_linear_rgb())
                    {
                        signal_invalid_sample();
                        continue;
                    }

                    // Merge the sample into the scratch framebuffer.
                    m_scratch_fb->add(
                        static_cast<float>(m_scratch_fb_half_width + s.x),
                        static_cast<float>(m_scratch_fb_half_height + s.y),
                        shading_result);

                    // Update statistics for this pixel.
                    // todo: variation should be computed in a user-selectable color space, typically the target color space.
                    // todo: one tracker per AOV?
                    trackers[0].insert(shading_result.m_main.m_color[0]);
                    trackers[1].insert(shading_result.m_main.m_color[1]);
                    trackers[2].insert(shading_result.m_main.m_color[2]);
                }

                // Stop if the variation criterion is met.
                if (trackers[0].get_variation() <= m_params.m_max_variation &&
                    trackers[1].get_variation() <= m_params.m_max_variation &&
                    trackers[2].get_variation() <= m_params.m_max_variation)
                    break;
            }

            // Merge the scratch framebuffer into the output framebuffer.
            const float rcp_sample_count = 1.0f / trackers[0].get_size();
            for (int y = -m_scratch_fb_half_height; y <= m_scratch_fb_half_height; ++y)
            {
                for (int x = -m_scratch_fb_half_width; x <= m_scratch_fb_half_width; ++x)
                {
                    if (tile_bbox.contains(Vector2i(pt.x + x, pt.y + y)))
                    {
                        framebuffer.merge(                  // destination
                            pt.x + x,                       // destination X
                            pt.y + y,                       // destination Y
                            *m_scratch_fb.get(),            // source
                            m_scratch_fb_half_width + x,    // source X
                            m_scratch_fb_half_height + y,   // source Y
                            rcp_sample_count);              // scaling
                    }
                }
            }

            // Store diagnostics values in the diagnostics tile.
            if (m_params.m_diagnostics && tile_bbox.contains(pt))
            {
                Color<float, 2> values;

                values[0] =
                    saturate(
                        max(
                            trackers[0].get_variation(),
                            trackers[1].get_variation(),
                            trackers[2].get_variation())
                        / m_params.m_max_variation);

                values[1] =
                    m_params.m_min_samples == m_params.m_max_samples
                        ? 1.0f
                        : fit(
                            static_cast<float>(trackers[0].get_size()),
                            static_cast<float>(m_params.m_min_samples),
                            static_cast<float>(m_params.m_max_samples),
                            0.0f, 1.0f);

                m_diagnostics->set_pixel(pt.x, pt.y, values);
            }

            on_pixel_end(pi);
        }

        virtual StatisticsVector get_statistics() const APPLESEED_OVERRIDE
        {
            return m_sample_renderer->get_statistics();
        }

      private:
        struct Parameters
        {
            const SamplingContext::Mode     m_sampling_mode;
            const size_t                    m_min_samples;
            const size_t                    m_max_samples;
            const float                     m_max_variation;
            const bool                      m_diagnostics;

            explicit Parameters(const ParamArray& params)
              : m_sampling_mode(get_sampling_context_mode(params))
              , m_min_samples(params.get_required<size_t>("min_samples", 16))
              , m_max_samples(params.get_required<size_t>("max_samples", 256))
              , m_max_variation(pow(10.0f, -params.get_optional<float>("quality", 2.0f)))
              , m_diagnostics(params.get_optional<bool>("enable_diagnostics", false))
            {
            }
        };

        const Parameters                    m_params;
        auto_release_ptr<ISampleRenderer>   m_sample_renderer;
        size_t                              m_variation_aov_index;
        size_t                              m_samples_aov_index;
        int                                 m_scratch_fb_half_width;
        int                                 m_scratch_fb_half_height;
        auto_ptr<ShadingResultFrameBuffer>  m_scratch_fb;
        auto_ptr<Tile>                      m_diagnostics;

        static Color4f scalar_to_color(const float value)
        {
            static const Color4f Blue(0.0f, 0.0f, 1.0f, 1.0f);
            static const Color4f Red(1.0f, 0.0f, 0.0f, 1.0f);
            return lerp(Blue, Red, saturate(value));
        }
    };
}

//
// AdaptivePixelRendererFactory class implementation.
//

AdaptivePixelRendererFactory::AdaptivePixelRendererFactory(
    const Frame&                frame,
    ISampleRendererFactory*     factory,
    const ParamArray&           params)
  : m_frame(frame)
  , m_factory(factory)
  , m_params(params)
{
}

void AdaptivePixelRendererFactory::release()
{
    delete this;
}

IPixelRenderer* AdaptivePixelRendererFactory::create(
    const size_t                thread_index)
{
    return new AdaptivePixelRenderer(
        m_frame,
        m_factory,
        m_params,
        thread_index);
}

Dictionary AdaptivePixelRendererFactory::get_params_metadata()
{
    Dictionary metadata;

    metadata.dictionaries().insert(
        "min_samples",
        Dictionary()
            .insert("type", "int")
            .insert("default", "16")
            .insert("label", "Min Samples")
            .insert("help", "Minimum number of anti-aliasing samples"));

    metadata.dictionaries().insert(
        "max_samples",
        Dictionary()
            .insert("type", "int")
            .insert("default", "256")
            .insert("label", "Max Samples")
            .insert("help", "Maximum number of anti-aliasing samples"));

    metadata.dictionaries().insert(
        "quality",
        Dictionary()
            .insert("type", "float")
            .insert("default", "2.0")
            .insert("label", "Quality")
            .insert("help", "Quality factor"));

    metadata.dictionaries().insert(
        "enable_diagnostics",
        Dictionary()
            .insert("type", "bool")
            .insert("default", "false")
            .insert("label", "Enable Diagnostics")
            .insert(
                "help",
                "Enable adaptive sampling diagnostics"));

    return metadata;
}

}   // namespace renderer
<|endoftext|>


<commit_before>/**
 * Copyright (C) 2015 Virgil Security Inc.
 *
 * Lead Maintainer: Virgil Security Inc. <support@virgilsecurity.com>
 *
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met:
 *
 *     (1) Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *     (2) Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in
 *     the documentation and/or other materials provided with the
 *     distribution.
 *
 *     (3) Neither the name of the copyright holder nor the names of its
 *     contributors may be used to endorse or promote products derived from
 *     this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ''AS IS'' AND ANY EXPRESS OR
 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 */

#include <algorithm>
#include <fstream>
#include <iostream>
#include <iterator>
#include <map>
#include <stdexcept>
#include <string>

#include <tclap/CmdLine.h>

#include <virgil/crypto/VirgilByteArray.h>
#include <virgil/crypto/foundation/VirgilKeyPairGenerator.h>
#include <virgil/crypto/foundation/VirgilAsymmetricCipher.h>

#include <cli/version.h>
#include <cli/util.h>

using virgil::crypto::VirgilByteArray;
using virgil::crypto::foundation::VirgilKeyPairGenerator;
using virgil::crypto::foundation::VirgilAsymmetricCipher;

/**
 * @brief Convert string representation of the Elliptic Curve group to the appropriate constant.
 */
static VirgilKeyPairGenerator::ECKeyGroup ec_key_group_from_param(const std::string &param);

#ifdef SPLIT_CLI
#define MAIN main
#else
#define MAIN keygen_main
#endif

int MAIN(int argc, char **argv) {
    try {
        // Parse arguments.
        TCLAP::CmdLine cmd("Generate private key with given parameters.", ' ', virgil::cli_version());

        std::vector<std::string> ec_key;
        ec_key.push_back(" bp256r1 ");
        ec_key.push_back(" bp384r1 ");
        ec_key.push_back(" bp512r1 ");
        ec_key.push_back(" secp192r1 ");
        ec_key.push_back(" secp224r1 ");
        ec_key.push_back(" secp256r1 ");
        ec_key.push_back(" secp384r1 ");
        ec_key.push_back(" secp521r1 ");
        ec_key.push_back(" secp192k1 ");
        ec_key.push_back(" secp224k1 ");
        ec_key.push_back(" secp256k1 ");
        TCLAP::ValuesConstraint<std::string> allowedEcKey(ec_key);

        TCLAP::ValueArg<std::string> ecArg("e", "ec",
                "Generate elliptic curve key with one of the following curves:\n"
                "\t* bp256r1 - 256-bits Brainpool curve;\n"
                "\t* bp384r1 - 384-bits Brainpool curve;\n"
                "\t* bp512r1 - 512-bits Brainpool curve (default);\n"
                "\t* secp192r1 - 192-bits NIST curve;\n"
                "\t* secp224r1 - 224-bits NIST curve;\n"
                "\t* secp256r1 - 256-bits NIST curve;\n"
                "\t* secp384r1 - 384-bits NIST curve;\n"
                "\t* secp521r1 - 521-bits NIST curve;\n"
                "\t* secp192k1 - 192-bits \"Koblitz\" curve;\n"
                "\t* secp224k1 - 224-bits \"Koblitz\" curve;\n"
                "\t* secp256k1 - 256-bits \"Koblitz\" curve.\n",
                false, "bp512r1", &allowedEcKey);

        TCLAP::ValueArg<unsigned int> rsaArg("r", "rsa", "Generate RSA key with a given number of bits.",
                false, 0, "nbits");

        TCLAP::ValueArg<std::string> outArg("o", "out", "Private key. If omitted stdout is used.",
                false, "", "file");

        TCLAP::ValueArg<std::string> pwdArg("p", "pwd", "Password to be used for private key encryption. "
                "If omitted private key is stored in the plain format.", false, "", "arg");

        cmd.add(pwdArg);
        cmd.add(outArg);
        cmd.add(ecArg);
        cmd.add(rsaArg);

        cmd.parse(argc, argv);

        // Check parameters
        if (!ecArg.getValue().empty() && rsaArg.getValue() > 0) {
            throw std::invalid_argument("-e, --ec and -r, --rsa parameters are both specified");
        }

        VirgilAsymmetricCipher cipher = VirgilAsymmetricCipher::none();
        if (rsaArg.isSet()) {
            // Generate RSA key
            cipher = VirgilAsymmetricCipher::rsa();
            cipher.genKeyPair(VirgilKeyPairGenerator::rsa(rsaArg.getValue()));
        } else {
            // Generate EC key
            VirgilKeyPairGenerator::ECKeyGroup ecKeyGroup = ec_key_group_from_param(ecArg.getValue());
            if (ecKeyGroup == VirgilKeyPairGenerator::ECKeyGroup_DP_NONE) {
                if (ecArg.getValue().empty()) {
                    ecKeyGroup = VirgilKeyPairGenerator::ECKeyGroup_DP_BP512R1;
                } else {
                    throw std::invalid_argument(std::string("unknown elliptic curve: ") + ecArg.getValue());
                }
            }
            cipher = VirgilAsymmetricCipher::ec();
            cipher.genKeyPair(VirgilKeyPairGenerator::ec(ecKeyGroup));
        }

        // Export private key
        VirgilByteArray privateKey = cipher.exportPrivateKeyToPEM(virgil::crypto::str2bytes(pwdArg.getValue()));

        // Write private key
        virgil::cli::write_bytes(outArg.getValue(), privateKey);

    } catch (TCLAP::ArgException& exception) {
        std::cerr << "Error: " << exception.error() << " for arg " << exception.argId() << std::endl;
        return EXIT_FAILURE;
    } catch (std::exception& exception) {
        std::cerr << "Error: " << exception.what() << std::endl;
        return EXIT_FAILURE;
    }

    return EXIT_SUCCESS;
}

static VirgilKeyPairGenerator::ECKeyGroup ec_key_group_from_param(const std::string &param) {
    std::map<std::string, VirgilKeyPairGenerator::ECKeyGroup> ecKeyGroup;
    ecKeyGroup["secp192r1"] = VirgilKeyPairGenerator::ECKeyGroup_DP_SECP192R1;
    ecKeyGroup["secp224r1"] = VirgilKeyPairGenerator::ECKeyGroup_DP_SECP224R1;
    ecKeyGroup["secp256r1"] = VirgilKeyPairGenerator::ECKeyGroup_DP_SECP256R1;
    ecKeyGroup["secp384r1"] = VirgilKeyPairGenerator::ECKeyGroup_DP_SECP384R1;
    ecKeyGroup["secp521r1"] = VirgilKeyPairGenerator::ECKeyGroup_DP_SECP521R1;
    ecKeyGroup["bp256r1"] = VirgilKeyPairGenerator::ECKeyGroup_DP_BP256R1;
    ecKeyGroup["bp384r1"] = VirgilKeyPairGenerator::ECKeyGroup_DP_BP384R1;
    ecKeyGroup["bp512r1"] = VirgilKeyPairGenerator::ECKeyGroup_DP_BP512R1;
    ecKeyGroup["secp192k1"] = VirgilKeyPairGenerator::ECKeyGroup_DP_SECP192K1;
    ecKeyGroup["secp224k1"] = VirgilKeyPairGenerator::ECKeyGroup_DP_SECP224K1;
    ecKeyGroup["secp256k1"] = VirgilKeyPairGenerator::ECKeyGroup_DP_SECP256K1;

    auto group = ecKeyGroup.find(param);
    if (group != ecKeyGroup.end()) {
        return group->second;
    }
    return VirgilKeyPairGenerator::ECKeyGroup_DP_NONE;
}
<commit_msg>[CLI-7] Fix RSA and EC keys generation.<commit_after>/**
 * Copyright (C) 2015 Virgil Security Inc.
 *
 * Lead Maintainer: Virgil Security Inc. <support@virgilsecurity.com>
 *
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met:
 *
 *     (1) Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *     (2) Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in
 *     the documentation and/or other materials provided with the
 *     distribution.
 *
 *     (3) Neither the name of the copyright holder nor the names of its
 *     contributors may be used to endorse or promote products derived from
 *     this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ''AS IS'' AND ANY EXPRESS OR
 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 */

#include <algorithm>
#include <fstream>
#include <iostream>
#include <iterator>
#include <map>
#include <stdexcept>
#include <string>

#include <tclap/CmdLine.h>

#include <virgil/crypto/VirgilByteArray.h>
#include <virgil/crypto/foundation/VirgilKeyPairGenerator.h>
#include <virgil/crypto/foundation/VirgilAsymmetricCipher.h>

#include <cli/version.h>
#include <cli/util.h>

using virgil::crypto::VirgilByteArray;
using virgil::crypto::foundation::VirgilKeyPairGenerator;
using virgil::crypto::foundation::VirgilAsymmetricCipher;

/**
 * @brief Convert string representation of the Elliptic Curve group to the appropriate constant.
 */
static VirgilKeyPairGenerator::ECKeyGroup ec_key_group_from_param(const std::string &param);

#ifdef SPLIT_CLI
#define MAIN main
#else
#define MAIN keygen_main
#endif

int MAIN(int argc, char **argv) {
    try {
        // Parse arguments.
        TCLAP::CmdLine cmd("Generate private key with given parameters.", ' ', virgil::cli_version());

        std::vector<std::string> ec_key;
        ec_key.push_back("bp256r1");
        ec_key.push_back("bp384r1");
        ec_key.push_back("bp512r1");
        ec_key.push_back("secp192r1");
        ec_key.push_back("secp224r1");
        ec_key.push_back("secp256r1");
        ec_key.push_back("secp384r1");
        ec_key.push_back("secp521r1");
        ec_key.push_back("secp192k1");
        ec_key.push_back("secp224k1");
        ec_key.push_back("secp256k1");
        TCLAP::ValuesConstraint<std::string> allowedEcKey(ec_key);

        TCLAP::ValueArg<std::string> ecArg("e", "ec",
                "Generate elliptic curve key with one of the following curves:\n"
                "\t* bp256r1 - 256-bits Brainpool curve;\n"
                "\t* bp384r1 - 384-bits Brainpool curve;\n"
                "\t* bp512r1 - 512-bits Brainpool curve (default);\n"
                "\t* secp192r1 - 192-bits NIST curve;\n"
                "\t* secp224r1 - 224-bits NIST curve;\n"
                "\t* secp256r1 - 256-bits NIST curve;\n"
                "\t* secp384r1 - 384-bits NIST curve;\n"
                "\t* secp521r1 - 521-bits NIST curve;\n"
                "\t* secp192k1 - 192-bits \"Koblitz\" curve;\n"
                "\t* secp224k1 - 224-bits \"Koblitz\" curve;\n"
                "\t* secp256k1 - 256-bits \"Koblitz\" curve.\n",
                false, "", &allowedEcKey);

        TCLAP::ValueArg<unsigned int> rsaArg("r", "rsa", "Generate RSA key with a given number of bits.",
                false, 0, "nbits");

        TCLAP::ValueArg<std::string> outArg("o", "out", "Private key. If omitted stdout is used.",
                false, "", "file");

        TCLAP::ValueArg<std::string> pwdArg("p", "pwd", "Password to be used for private key encryption. "
                "If omitted private key is stored in the plain format.", false, "", "arg");

        cmd.add(pwdArg);
        cmd.add(outArg);
        cmd.add(ecArg);
        cmd.add(rsaArg);

        cmd.parse(argc, argv);

        // Check parameters
        if (ecArg.isSet() && rsaArg.isSet()) {
            throw std::invalid_argument("-e, --ec and -r, --rsa parameters are both specified");
        }

        VirgilAsymmetricCipher cipher = VirgilAsymmetricCipher::none();
        if (rsaArg.isSet()) {
            // Generate RSA key
            cipher = VirgilAsymmetricCipher::rsa();
            cipher.genKeyPair(VirgilKeyPairGenerator::rsa(rsaArg.getValue()));
        } else {
            // Generate EC key
            VirgilKeyPairGenerator::ECKeyGroup ecKeyGroup = ec_key_group_from_param(ecArg.getValue());
            if (ecKeyGroup == VirgilKeyPairGenerator::ECKeyGroup_DP_NONE) {
                if (ecArg.getValue().empty()) {
                    ecKeyGroup = VirgilKeyPairGenerator::ECKeyGroup_DP_BP512R1;
                } else {
                    throw std::invalid_argument(std::string("unknown elliptic curve: ") + ecArg.getValue());
                }
            }
            cipher = VirgilAsymmetricCipher::ec();
            cipher.genKeyPair(VirgilKeyPairGenerator::ec(ecKeyGroup));
        }

        // Export private key
        VirgilByteArray privateKey = cipher.exportPrivateKeyToPEM(virgil::crypto::str2bytes(pwdArg.getValue()));

        // Write private key
        virgil::cli::write_bytes(outArg.getValue(), privateKey);

    } catch (TCLAP::ArgException& exception) {
        std::cerr << "Error: " << exception.error() << " for arg " << exception.argId() << std::endl;
        return EXIT_FAILURE;
    } catch (std::exception& exception) {
        std::cerr << "Error: " << exception.what() << std::endl;
        return EXIT_FAILURE;
    }

    return EXIT_SUCCESS;
}

static VirgilKeyPairGenerator::ECKeyGroup ec_key_group_from_param(const std::string &param) {
    std::map<std::string, VirgilKeyPairGenerator::ECKeyGroup> ecKeyGroup;
    ecKeyGroup["secp192r1"] = VirgilKeyPairGenerator::ECKeyGroup_DP_SECP192R1;
    ecKeyGroup["secp224r1"] = VirgilKeyPairGenerator::ECKeyGroup_DP_SECP224R1;
    ecKeyGroup["secp256r1"] = VirgilKeyPairGenerator::ECKeyGroup_DP_SECP256R1;
    ecKeyGroup["secp384r1"] = VirgilKeyPairGenerator::ECKeyGroup_DP_SECP384R1;
    ecKeyGroup["secp521r1"] = VirgilKeyPairGenerator::ECKeyGroup_DP_SECP521R1;
    ecKeyGroup["bp256r1"] = VirgilKeyPairGenerator::ECKeyGroup_DP_BP256R1;
    ecKeyGroup["bp384r1"] = VirgilKeyPairGenerator::ECKeyGroup_DP_BP384R1;
    ecKeyGroup["bp512r1"] = VirgilKeyPairGenerator::ECKeyGroup_DP_BP512R1;
    ecKeyGroup["secp192k1"] = VirgilKeyPairGenerator::ECKeyGroup_DP_SECP192K1;
    ecKeyGroup["secp224k1"] = VirgilKeyPairGenerator::ECKeyGroup_DP_SECP224K1;
    ecKeyGroup["secp256k1"] = VirgilKeyPairGenerator::ECKeyGroup_DP_SECP256K1;

    auto group = ecKeyGroup.find(param);
    if (group != ecKeyGroup.end()) {
        return group->second;
    }
    return VirgilKeyPairGenerator::ECKeyGroup_DP_NONE;
}
<|endoftext|>


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

// system headers
#include <ctype.h>
#include <stdio.h>

// class-specific headers
#include "CommandManager.h"
#include "TextUtils.h"

CommandManager::CommandManager()
{
  // do nothing
}

CommandManager::~CommandManager()
{
  // do nothing
}

void				CommandManager::add(const std::string& name,
						    CommandFunction func,
						    const std::string& help)
{
  commands.erase(name);
  CmdInfo info;
  info.func = func;
  info.help = help;
  commands.insert(std::make_pair(name, info));
}

void				CommandManager::remove(const std::string& name)
{
  commands.erase(name);
}

std::string			CommandManager::getHelp(const std::string& name) const
{
  // look up command
  Commands::const_iterator index = commands.find(name);
  if (index == commands.end())
    return "";

  // return help string
  return index->second.help;
}

std::string			CommandManager::run(const std::string& name,
							    const ArgList& args) const
{
  // look up command
  Commands::const_iterator index = commands.find(name);
  if (index == commands.end())
    return string_util::format("Command %s not found", name.c_str());

  // run it
  return (*index->second.func)(name, args);
}

std::string			CommandManager::run(const std::string& cmd) const
{
  std::string result;
  const char* scan = cmd.c_str();

  scan = skipWhitespace(scan);
  while (scan != NULL && *scan != '\0') {
    std::string name;
    ArgList args;

    // parse command name
    scan = skipWhitespace(scan);
    scan = readValue(scan, &name);
    if (scan != NULL)
      scan = skipWhitespace(scan);

    // parse arguments
    while (scan != NULL && *scan != '\0' && *scan != ';') {
      std::string value;
      scan = readValue(scan, &value);
      if (scan != NULL) {
        scan = skipWhitespace(scan);
        args.push_back(value);
      }
    }

    // run it or report error
    if (scan == NULL)
      return std::string("Error parsing command");
    else
      result = run(name, args);

    // discard ; and empty commands
    while (scan != NULL && *scan == ';') {
      ++scan;
      scan = skipWhitespace(scan);
    }
  }

  // return result of last command only
  return result;
}

void				CommandManager::iterate(Callback callback,
							void* userData) const
{
  assert(callback != NULL);

  for (Commands::const_iterator index = commands.begin();
       index != commands.end(); ++index)
    (*callback)(index->first, userData);
}

const char*			CommandManager::readValue(const char* string,
							  std::string* value)
{
  if (*string == '\"')
    return readQuoted(string + 1, value);
  else if (*string != '\0')
    return readUnquoted(string, value);
  else
    return string;
}

const char*			CommandManager::readUnquoted(const char* string,
							     std::string* value)
{
  // read up to next whitespace.  escapes are not interpreted.
  const char* start = string;
  while (*string != '\0' && !isspace(*string) && *string != ';')
    ++string;
  *value = std::string(start, string - start);
  return string;
}

const char*			CommandManager::readQuoted(const char* string,
							   std::string* value)
{
  *value = "";
  bool escaped = false;
  for (; *string != '\0'; ++string) {
    if (escaped) {
      switch (*string) {
        case 't': value->append("\t", 1); break;
        case 'n': value->append("\n", 1); break;
        case 'r': value->append("\r", 1); break;
        case '\\': value->append("\\", 1); break;
        case '\"': value->append("\"", 1); break;
        default: value->append(string, 1); break;
      }
      escaped = false;
    } else if (*string == '\\') {
      escaped = true;
    } else if (*string == '\"') {
      return string + 1;
    } else {
      value->append(string, 1);
    }
  }
  // closing quote is missing.  if escaped is true the called may have
  // wanted to continue the line but we don't allow that.
  return NULL;
}

const char*			CommandManager::skipWhitespace(const char* string)
{
  while (*string != '\0' && isspace(*string))
    ++string;
  return string;
}

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

<commit_msg>stop the sym-trunc warnings<commit_after>/* bzflag
 * Copyright (c) 1993 - 2003 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.
 */

#ifdef _WIN32
#pragma warning(4:4786)
#endif

// system headers
#include <ctype.h>
#include <stdio.h>

// class-specific headers
#include "CommandManager.h"
#include "TextUtils.h"

CommandManager::CommandManager()
{
  // do nothing
}

CommandManager::~CommandManager()
{
  // do nothing
}

void				CommandManager::add(const std::string& name,
						    CommandFunction func,
						    const std::string& help)
{
  commands.erase(name);
  CmdInfo info;
  info.func = func;
  info.help = help;
  commands.insert(std::make_pair(name, info));
}

void				CommandManager::remove(const std::string& name)
{
  commands.erase(name);
}

std::string			CommandManager::getHelp(const std::string& name) const
{
  // look up command
  Commands::const_iterator index = commands.find(name);
  if (index == commands.end())
    return "";

  // return help string
  return index->second.help;
}

std::string			CommandManager::run(const std::string& name,
							    const ArgList& args) const
{
  // look up command
  Commands::const_iterator index = commands.find(name);
  if (index == commands.end())
    return string_util::format("Command %s not found", name.c_str());

  // run it
  return (*index->second.func)(name, args);
}

std::string			CommandManager::run(const std::string& cmd) const
{
  std::string result;
  const char* scan = cmd.c_str();

  scan = skipWhitespace(scan);
  while (scan != NULL && *scan != '\0') {
    std::string name;
    ArgList args;

    // parse command name
    scan = skipWhitespace(scan);
    scan = readValue(scan, &name);
    if (scan != NULL)
      scan = skipWhitespace(scan);

    // parse arguments
    while (scan != NULL && *scan != '\0' && *scan != ';') {
      std::string value;
      scan = readValue(scan, &value);
      if (scan != NULL) {
        scan = skipWhitespace(scan);
        args.push_back(value);
      }
    }

    // run it or report error
    if (scan == NULL)
      return std::string("Error parsing command");
    else
      result = run(name, args);

    // discard ; and empty commands
    while (scan != NULL && *scan == ';') {
      ++scan;
      scan = skipWhitespace(scan);
    }
  }

  // return result of last command only
  return result;
}

void				CommandManager::iterate(Callback callback,
							void* userData) const
{
  assert(callback != NULL);

  for (Commands::const_iterator index = commands.begin();
       index != commands.end(); ++index)
    (*callback)(index->first, userData);
}

const char*			CommandManager::readValue(const char* string,
							  std::string* value)
{
  if (*string == '\"')
    return readQuoted(string + 1, value);
  else if (*string != '\0')
    return readUnquoted(string, value);
  else
    return string;
}

const char*			CommandManager::readUnquoted(const char* string,
							     std::string* value)
{
  // read up to next whitespace.  escapes are not interpreted.
  const char* start = string;
  while (*string != '\0' && !isspace(*string) && *string != ';')
    ++string;
  *value = std::string(start, string - start);
  return string;
}

const char*			CommandManager::readQuoted(const char* string,
							   std::string* value)
{
  *value = "";
  bool escaped = false;
  for (; *string != '\0'; ++string) {
    if (escaped) {
      switch (*string) {
        case 't': value->append("\t", 1); break;
        case 'n': value->append("\n", 1); break;
        case 'r': value->append("\r", 1); break;
        case '\\': value->append("\\", 1); break;
        case '\"': value->append("\"", 1); break;
        default: value->append(string, 1); break;
      }
      escaped = false;
    } else if (*string == '\\') {
      escaped = true;
    } else if (*string == '\"') {
      return string + 1;
    } else {
      value->append(string, 1);
    }
  }
  // closing quote is missing.  if escaped is true the called may have
  // wanted to continue the line but we don't allow that.
  return NULL;
}

const char*			CommandManager::skipWhitespace(const char* string)
{
  while (*string != '\0' && isspace(*string))
    ++string;
  return string;
}

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

<|endoftext|>


<commit_before>#include "condor_common.h"
#include <sys/socket.h>
#include <netinet/in.h>

#if !defined(LINUX) && !defined(HPUX9)
#include <sys/select.h>
#endif

#include "condor_types.h"
#include "condor_debug.h"
#include "condor_expressions.h"
#include "condor_mach_status.h"
#include "condor_attributes.h"
#include "sched.h"

#include "event.h"
#include "state.h"
#include "resource.h"
#include "resmgr.h"

extern ClassAd* template_ClassAd;

static char *_FileName_ = __FILE__;

/*
 * Higher level routines to manage a collection of resources.
 * XXX - DON'T do this using lineair searches..
 */

static resource_info_t *resources=NULL;
static int nresources;
static fd_set cur_fds;

static int resmgr_vacateone(resource_info_t *);
static int resmgr_addfd(resource_info_t *);
static int resmgr_command(resource_info_t *);
void update_central_mgr(void);

extern "C" int resmgr_setsocks(fd_set* fds);
extern "C" int resmgr_call(fd_set* fds);
extern "C" void resmgr_changestate(resource_id_t rid, int new_state);

// collect all resources that were listed in the config file
// initialize(including the ClassAd in each resource)
//  and store them in the global resources array. The number
// of such resources (just 1 if RESOURCE_LIST i snot specified
// in the config \file is recorded by nresources.
int resmgr_init()
{
	int nres, i, index;
	resource_name_t *rnames;
	resource_id_t rid;
	resource_param_t param;

	// collect all resources that were listed in the config file
	// and their number
	resource_names(&rnames, &nres);
	dprintf(D_ALWAYS, "resmgr_init: %d resources.\n", nres);
	resources = (resource_info_t *)calloc(nres, (sizeof (resource_info_t)));
	for (i = index = 0; i < nres; i++) {
		dprintf(D_ALWAYS, "opening resource '%s'\n", rnames[i]);
		if (resource_open(rnames[i], &rid) < 0)
			continue;
		resources[index].r_rid = rid;
		dprintf(D_ALWAYS, "resource %d has id '%s'\n", index,
			resources[index].r_rid);
		resources[index].r_state = NO_JOB;
		if (resource_params(rid, NO_JID, NO_TID,
		    &resources[index].r_param, NULL) < 0)
			continue;
		resources[index].r_name = rnames[i];
		resources[index].r_pid = NO_PID;
		resources[index].r_claimed = FALSE;
		// C H A N G E -> N Anand
		resources[index].r_context = new ClassAd(*template_ClassAd);
		resources[index].r_jobcontext = NULL;
		resources[index].r_capab = NULL;
		resources[index].r_interval = 0;
		resources[index].r_receivetime = 0;
		resources[index].r_universe = STANDARD;
		dprintf(D_FULLDEBUG, "create_context returned %x\n",
			resources[index].r_context);
		resources[index].r_port = create_port(&resources[index].r_sock);
		// CHANGE -> N Anand
		resource_initAd(&resources[index]);
		/* XXX following must be last in this initialization */
		resource_context(&resources[index]);
		index++;
	}
	nresources = index;
	dprintf(D_ALWAYS, "nresources set to %d\n", nresources);
	return 0;
}

int
resmgr_setsocks(fd_set* fds)
{
	FD_ZERO(&cur_fds);
	resmgr_walk(resmgr_addfd);
	*fds = cur_fds;
	return 0;
}

int
resmgr_call(fd_set* fds)
{
	cur_fds = *fds;
	return resmgr_walk(resmgr_command);
}

int
resmgr_add(resource_id_t rid, resource_info_t* rinfop)
{
	int i;

	for (i = 0; i < nresources; i++) {
		if (resource_isused(resources[i])) {
			resources[i] = *rinfop;
			break;
		}
	}
	return i == nresources ? -1 : 0;
}

int
resmgr_del(resource_id_t rid)
{
	int i;

	for (i = 0; i < nresources; i++) {
		if (!resource_isused(resources[i]))
			continue;
		if (!resource_ridcmp(resources[i].r_rid, rid)) {
			resource_markunused(resources[i]);
			break;
		}
	}
	return i == nresources ? -1 : 0;
}

resource_info_t *
resmgr_getbyrid(resource_id_t rid)
{
	int i;

	for (i = 0; i < nresources; i++) {
		if (!resource_ridcmp(resources[i].r_rid, rid))
			return &resources[i];
	}
	return (resource_info_t *)0;
}

resource_info_t *
resmgr_getbyname(resource_name_t rname)
{
	int i;

	for (i = 0; i < nresources; i++) {
		if (!resource_rnamecmp(resources[i].r_name, rname))
			return &resources[i];
	}
	return (resource_info_t *)0;
}

resource_info_t *
resmgr_getbypid(int pid)
{
	int i;

	for (i = 0; i < nresources; i++) {
		if (resources[i].r_pid == pid)
			return &resources[i];
	}
	return (resource_info_t *)0;
}

int
resmgr_walk(int (*func)(resource_info_t*))
{
	int i;

	for (i = 0; i < nresources; i++)
		func(&resources[i]);
	return 0;
}

int
resmgr_vacateall(void)
{
	return resmgr_walk(resmgr_vacateone);
}

bool
resmgr_resourceinuse(void)
{
	int i;

	for (i = 0; i < nresources; i++)
		if (resources[i].r_state != NO_JOB) return true;
	return false;
}

static int
resmgr_vacateone(resource_info_t* rinfop)
{
	resource_id_t rid;

	rid = rinfop->r_rid;
	return resource_event(rid, NO_JID, NO_TID, EV_VACATE);
}

static int
resmgr_addfd(resource_info_t* rip)
{
	FD_SET(rip->r_sock, &cur_fds);
	return 0;
}

static int
resmgr_command(resource_info_t* rinfop)
{
	if (FD_ISSET(rinfop->r_sock, &cur_fds)) {
		call_incoming(rinfop->r_sock, SOCK_STREAM, rinfop->r_rid);
		FD_CLR(rinfop->r_sock , &cur_fds);
	}
	return 0;
}

ClassAd*
resmgr_context(resource_id_t rid)
{
	resource_info_t *rip;

	if (!(rip = resmgr_getbyrid(rid)))
		return NULL;

	return rip->r_context;
}

char *
state_to_string(int state)
{
	switch (state) {
	case NO_JOB:
		return "NoJob";
	case JOB_RUNNING:
		return "Running";
	case KILLED:
		return "Killed";
	case CHECKPOINTING:
		return "Checkpointing";
	case SUSPENDED:
		return "Suspended";
	case BLOCKED:
		return "Blocked";
	case SYSTEM:
		return "System";
	}
	return "Unknown";
}

void resmgr_changestate(resource_id_t rid, int new_state)
{
  ClassAd* cp;
  char *name;
  char tmp[80];
  int start = FALSE;
  int claimed;
  resource_info_t *rip;

  if (!(rip = resmgr_getbyrid(rid)))
    return;

  cp = rip->r_context;
  claimed = rip->r_claimed;

  switch (new_state)
  {
   case NO_JOB:
    cp->EvalBool(ATTR_REQUIREMENTS, template_ClassAd, start);
    if(start && claimed == FALSE )
    {
      set_machine_status(M_IDLE);
    }
    else
    {
      set_machine_status(USER_BUSY);
    }
    cp->Delete("ClientMachine");
    cp->Delete("RemoteUser");
    cp->Delete("JobId");
    cp->Delete("JobStart");
  case JOB_RUNNING:
    set_machine_status(JOB_RUNNING);
    break;
  case KILLED:
    set_machine_status(KILLED);
    break;
  case CHECKPOINTING:
    set_machine_status(CHECKPOINTING);
    break;
  case SUSPENDED:
    set_machine_status(SUSPENDED);
    break;
  case BLOCKED:
    set_machine_status(BLOCKED);
    break;
  case SYSTEM:
    set_machine_status(SYSTEM);
    break;
  default:
    EXCEPT("Change states, unknown state (%d)", new_state);
 }

  name = state_to_string(new_state);
  rip->r_state = new_state;

  sprintf(tmp,"State=\"%s\"",name);
  cp->InsertOrUpdate(tmp);

  sprintf(tmp,"EnteredCurrentState=%d",(int)time((time_t*)0));
  cp->InsertOrUpdate(tmp);

  update_central_mgr();
}
<commit_msg>Removed all mention of "context" from variable names, etc.  Also, made changes for update vs. timeout stuff described in the log for event.C or main.C<commit_after>#include "condor_common.h"
#include <sys/socket.h>
#include <netinet/in.h>

#if !defined(LINUX) && !defined(HPUX9)
#include <sys/select.h>
#endif

#include "condor_types.h"
#include "condor_debug.h"
#include "condor_expressions.h"
#include "condor_mach_status.h"
#include "condor_attributes.h"
#include "sched.h"

#include "event.h"
#include "state.h"
#include "resource.h"
#include "resmgr.h"

extern ClassAd* template_ClassAd;

static char *_FileName_ = __FILE__;

/*
 * Higher level routines to manage a collection of resources.
 * XXX - DON'T do this using lineair searches..
 */

static resource_info_t *resources=NULL;
static int nresources;
static fd_set cur_fds;

static int resmgr_vacateone(resource_info_t *);
static int resmgr_addfd(resource_info_t *);
static int resmgr_command(resource_info_t *);
void update_central_mgr(void);

extern "C" int resmgr_setsocks(fd_set* fds);
extern "C" int resmgr_call(fd_set* fds);
extern "C" void resmgr_changestate(resource_id_t rid, int new_state);

// collect all resources that were listed in the config file
// initialize(including the ClassAd in each resource)
//  and store them in the global resources array. The number
// of such resources (just 1 if RESOURCE_LIST i snot specified
// in the config \file is recorded by nresources.
int resmgr_init()
{
	int nres, i, index;
	resource_name_t *rnames;
	resource_id_t rid;
	resource_param_t param;

	// collect all resources that were listed in the config file
	// and their number
	resource_names(&rnames, &nres);
	dprintf(D_ALWAYS, "resmgr_init: %d resources.\n", nres);
	resources = (resource_info_t *)calloc(nres, (sizeof (resource_info_t)));
	for (i = index = 0; i < nres; i++) {
		dprintf(D_ALWAYS, "opening resource '%s'\n", rnames[i]);
		if (resource_open(rnames[i], &rid) < 0)
			continue;
		resources[index].r_rid = rid;
		dprintf(D_ALWAYS, "resource %d has id '%s'\n", index,
			resources[index].r_rid);
		resources[index].r_state = NO_JOB;
		if (resource_timeout_params(rid, NO_JID, NO_TID,
		    &resources[index].r_param, NULL) < 0)
			continue;
		if (resource_update_params(rid, NO_JID, NO_TID,
		    &resources[index].r_param, NULL) < 0)
			continue;
		resources[index].r_name = rnames[i];
		resources[index].r_pid = NO_PID;
		resources[index].r_claimed = FALSE;
		// C H A N G E -> N Anand
		resources[index].r_classad = new ClassAd(*template_ClassAd);
		resources[index].r_jobclassad = NULL;
		resources[index].r_capab = NULL;
		resources[index].r_interval = 0;
		resources[index].r_receivetime = 0;
		resources[index].r_universe = STANDARD;
		dprintf(D_FULLDEBUG, "create_classad returned %x\n",
			resources[index].r_classad);
		resources[index].r_port = create_port(&resources[index].r_sock);
		// CHANGE -> N Anand
		resource_initAd(&resources[index]);
		/* XXX following must be last in this initialization */
		resource_timeout_classad(&resources[index]);
		resource_update_classad(&resources[index]);
		index++;
	}
	nresources = index;
	dprintf(D_ALWAYS, "nresources set to %d\n", nresources);
	return 0;
}

int
resmgr_setsocks(fd_set* fds)
{
	FD_ZERO(&cur_fds);
	resmgr_walk(resmgr_addfd);
	*fds = cur_fds;
	return 0;
}

int
resmgr_call(fd_set* fds)
{
	cur_fds = *fds;
	return resmgr_walk(resmgr_command);
}

int
resmgr_add(resource_id_t rid, resource_info_t* rinfop)
{
	int i;

	for (i = 0; i < nresources; i++) {
		if (resource_isused(resources[i])) {
			resources[i] = *rinfop;
			break;
		}
	}
	return i == nresources ? -1 : 0;
}

int
resmgr_del(resource_id_t rid)
{
	int i;

	for (i = 0; i < nresources; i++) {
		if (!resource_isused(resources[i]))
			continue;
		if (!resource_ridcmp(resources[i].r_rid, rid)) {
			resource_markunused(resources[i]);
			break;
		}
	}
	return i == nresources ? -1 : 0;
}

resource_info_t *
resmgr_getbyrid(resource_id_t rid)
{
	int i;

	for (i = 0; i < nresources; i++) {
		if (!resource_ridcmp(resources[i].r_rid, rid))
			return &resources[i];
	}
	return (resource_info_t *)0;
}

resource_info_t *
resmgr_getbyname(resource_name_t rname)
{
	int i;

	for (i = 0; i < nresources; i++) {
		if (!resource_rnamecmp(resources[i].r_name, rname))
			return &resources[i];
	}
	return (resource_info_t *)0;
}

resource_info_t *
resmgr_getbypid(int pid)
{
	int i;

	for (i = 0; i < nresources; i++) {
		if (resources[i].r_pid == pid)
			return &resources[i];
	}
	return (resource_info_t *)0;
}

int
resmgr_walk(int (*func)(resource_info_t*))
{
	int i;

	for (i = 0; i < nresources; i++)
		func(&resources[i]);
	return 0;
}

int
resmgr_vacateall(void)
{
	return resmgr_walk(resmgr_vacateone);
}

bool
resmgr_resourceinuse(void)
{
	int i;

	for (i = 0; i < nresources; i++)
		if (resources[i].r_state != NO_JOB) return true;
	return false;
}

static int
resmgr_vacateone(resource_info_t* rinfop)
{
	resource_id_t rid;

	rid = rinfop->r_rid;
	return resource_event(rid, NO_JID, NO_TID, EV_VACATE);
}

static int
resmgr_addfd(resource_info_t* rip)
{
	FD_SET(rip->r_sock, &cur_fds);
	return 0;
}

static int
resmgr_command(resource_info_t* rinfop)
{
	if (FD_ISSET(rinfop->r_sock, &cur_fds)) {
		call_incoming(rinfop->r_sock, SOCK_STREAM, rinfop->r_rid);
		FD_CLR(rinfop->r_sock , &cur_fds);
	}
	return 0;
}

ClassAd*
resmgr_classad(resource_id_t rid)
{
	resource_info_t *rip;

	if (!(rip = resmgr_getbyrid(rid)))
		return NULL;

	return rip->r_classad;
}

char *
state_to_string(int state)
{
	switch (state) {
	case NO_JOB:
		return "NoJob";
	case JOB_RUNNING:
		return "Running";
	case KILLED:
		return "Killed";
	case CHECKPOINTING:
		return "Checkpointing";
	case SUSPENDED:
		return "Suspended";
	case BLOCKED:
		return "Blocked";
	case SYSTEM:
		return "System";
	}
	return "Unknown";
}

void resmgr_changestate(resource_id_t rid, int new_state)
{
  ClassAd* cp;
  char *name;
  char tmp[80];
  int start = FALSE;
  int claimed;
  resource_info_t *rip;

  if (!(rip = resmgr_getbyrid(rid)))
    return;

  cp = rip->r_classad;
  claimed = rip->r_claimed;

  switch (new_state)
  {
   case NO_JOB:
    cp->EvalBool(ATTR_REQUIREMENTS, template_ClassAd, start);
    if(start && claimed == FALSE )
    {
      set_machine_status(M_IDLE);
    }
    else
    {
      set_machine_status(USER_BUSY);
    }
    cp->Delete("ClientMachine");
    cp->Delete("RemoteUser");
    cp->Delete("JobId");
    cp->Delete("JobStart");
  case JOB_RUNNING:
    set_machine_status(JOB_RUNNING);
    break;
  case KILLED:
    set_machine_status(KILLED);
    break;
  case CHECKPOINTING:
    set_machine_status(CHECKPOINTING);
    break;
  case SUSPENDED:
    set_machine_status(SUSPENDED);
    break;
  case BLOCKED:
    set_machine_status(BLOCKED);
    break;
  case SYSTEM:
    set_machine_status(SYSTEM);
    break;
  default:
    EXCEPT("Change states, unknown state (%d)", new_state);
 }

  name = state_to_string(new_state);
  rip->r_state = new_state;

  sprintf(tmp,"State=\"%s\"",name);
  cp->InsertOrUpdate(tmp);

  sprintf(tmp,"EnteredCurrentState=%d",(int)time((time_t*)0));
  cp->InsertOrUpdate(tmp);

  update_central_mgr();
}
<|endoftext|>