<commit_before>/*
 * HyPerCol.cpp
 *
 *  Created on: Jul 30, 2008
 *      Author: Craig Rasmussen
 */

#define TIMER_ON
#undef TIMESTEP_OUTPUT

#include "HyPerCol.hpp"
#include "InterColComm.hpp"
#include "../connections/PVConnection.h"
#include "../io/clock.h"
#include "../io/imageio.hpp"
#include "../io/io.h"
#include "../utils/pv_random.h"

#include <assert.h>
#include <math.h>
#include <memory.h>
#include <stdio.h>
#include <stdlib.h>

namespace PV {

HyPerCol::HyPerCol(const char * name, int argc, char * argv[])
         : warmStart(false), isInitialized(false)
{
   int opencl_device = 1;  // default to CPU for now

   // TODO - fix these numbers to dynamically grow
   maxLayers = MAX_LAYERS;
   maxConnections = MAX_CONNECTIONS;

   this->name = strdup(name);
   this->runTimer = new Timer();

   char * param_file;
   simTime = 0;
   numLayers = 0;
   numConnections = 0;
   layers = (HyPerLayer **) malloc(maxLayers * sizeof(HyPerLayer *));
   connections = (HyPerConn **) malloc(maxConnections * sizeof(HyPerConn *));

   numSteps = 2;
   image_file = NULL;
   param_file = NULL;
   unsigned long random_seed = 0;
   parse_options(argc, argv, &image_file, &param_file, &numSteps, &opencl_device, &random_seed);

   // run only on CPU for now
   initializeThreads(opencl_device);

   // estimate for now
   // TODO -get rid of maxGroups
   int maxGroups = 2*(maxLayers + maxConnections);
   params = new PVParams(param_file, maxGroups);

   icComm = new InterColComm(&argc, &argv);

   // initialize random seed
   //
   random_seed = getRandomSeed();
   random_seed = params->value(name, "randomSeed", random_seed);
   pv_srandom(random_seed);

   if (param_file != NULL) free(param_file);

   deltaTime = DELTA_T;
   if (params->present(name, "dt")) deltaTime = params->value(name, "dt");

   int status = -1;
   if (image_file) {
      status = getImageInfo(image_file, icComm, &imageLoc);
   }

   if (status) {
      imageLoc.nxGlobal = (int) params->value(name, "nx");
      imageLoc.nyGlobal = (int) params->value(name, "ny");

      // set loc based on global parameters and processor partitioning
      //
      setLayerLoc(&imageLoc, 1.0f, 1.0f, 0, 1);
   }

   runDelegate = NULL;

   numProbes = 0;
   probes = NULL;
}

HyPerCol::~HyPerCol()
{
   int n;

   finalizeThreads();

   if (image_file != NULL) free(image_file);

   for (n = 0; n < numConnections; n++) {
      delete connections[n];
   }

   for (n = 0; n < numLayers; n++) {
      // TODO: check to see if finalize called
      if (layers[n] != NULL) {
         delete layers[n]; // will call *_finalize
      }
      else {
         // TODO move finalize
         // PVLayer_finalize(getCLayer(n));
      }
   }

   delete icComm;

   printf("%16s: total time in %6s %10s: ", name, "column", "run");
   runTimer->elapsed_time();
   delete runTimer;

   free(connections);
   free(layers);
   free(name);
}

int HyPerCol::initFinish(void)
{
   int status = 0;

   for (int i = 0; i < this->numLayers; i++) {
      status = layers[i]->initFinish();
      if (status != 0) {
         fprintf(stderr, "[%d]: HyPerCol::initFinish: ERROR condition, exiting...\n", this->columnId());
         exit(status);
      }
   }

   log_parameters(numSteps, image_file);

   isInitialized = true;

   return status;
}

int HyPerCol::columnId()
{
   return icComm->commRank();
}

int HyPerCol::numberOfColumns()
{
   return icComm->numCommRows() * icComm->numCommColumns();
}

int HyPerCol::commColumn(int colId)
{
   return colId % icComm->numCommColumns();
}

int HyPerCol::commRow(int colId)
{
   return colId / icComm->numCommColumns();
}

int HyPerCol::setLayerLoc(PVLayerLoc * layerLoc,
                          float nxScale, float nyScale, int margin, int nf)
{
   layerLoc->nxGlobal = (int) (nxScale * imageLoc.nxGlobal);
   layerLoc->nyGlobal = (int) (nyScale * imageLoc.nyGlobal);

   // partition input space based on the number of processor
   // columns and rows
   //

   layerLoc->nx = layerLoc->nxGlobal / icComm->numCommColumns();
   layerLoc->ny = layerLoc->nyGlobal / icComm->numCommRows();

   assert(layerLoc->nxGlobal == layerLoc->nx * icComm->numCommColumns());
   assert(layerLoc->nyGlobal == layerLoc->ny * icComm->numCommRows());

   layerLoc->kx0 = layerLoc->nx * icComm->commColumn();
   layerLoc->ky0 = layerLoc->ny * icComm->commRow();

   layerLoc->nf = nf;
   layerLoc->nb = margin;

   layerLoc->halo.lt = margin;
   layerLoc->halo.rt = margin;
   layerLoc->halo.dn = margin;
   layerLoc->halo.up = margin;

   return 0;
}

int HyPerCol::addLayer(HyPerLayer * l)
{
   assert(numLayers < maxLayers);
   l->columnWillAddLayer(icComm, numLayers);
   layers[numLayers++] = l;
   return (numLayers - 1);
}

int HyPerCol::addConnection(HyPerConn * conn)
{
   int connId = numConnections;

   assert(numConnections < maxConnections);

   // numConnections is the ID of this connection
   icComm->subscribe(conn);

   connections[numConnections++] = conn;

   return connId;
}

int HyPerCol::run(int nTimeSteps)
{
   checkMarginWidths();

   int step = 0;
   float stopTime = simTime + nTimeSteps * deltaTime;
   const bool exitOnFinish = false;

   if (!isInitialized) {
      initFinish();
   }

   numSteps = nTimeSteps;

#ifdef DEBUG_OUTPUT
   if (columnId() == 0) {
      printf("[0]: HyPerCol: running...\n");  fflush(stdout);
   }
#endif

   // publish initial conditions
   //
   for (int l = 0; l < numLayers; l++) {
      layers[l]->publish(icComm, simTime);
   }

   // wait for all published data to arrive
   //
   for (int l = 0; l < numLayers; l++) {
      icComm->wait(layers[l]->getLayerId());
   }

   if (runDelegate) {
      // let delegate advance the time
      //
      runDelegate->run(simTime, stopTime);
   }

#ifdef TIMER_ON
      start_clock();
#endif
   // time loop
   //
   while (simTime < stopTime) {
      simTime = advanceTime(simTime);
      step += 1;

#ifdef TIMER_ON
      if (step == 10) start_clock();
#endif

   }  // end time loop

#ifdef DEBUG_OUTPUT
   if (columnId() == 0) {
      printf("[0]: HyPerCol::run done...\n");  fflush(stdout);
   }
#endif

   exitRunLoop(exitOnFinish);

#ifdef TIMER_ON
      stop_clock();
#endif

   return 0;
}

float HyPerCol::advanceTime(float sim_time)
{
#ifdef TIMESTEP_OUTPUT
   int nstep = (int) (sim_time/getDeltaTime());
   if (nstep%2000 == 0 && columnId() == 0) {
      printf("   [%d]: time==%f\n", columnId(), sim_time);
   }
#endif

   runTimer->start();

   // At this point all activity from the previous time step have
   // been delivered to the data store.
   //

   // update the connections (weights)
   //
   for (int c = 0; c < numConnections; c++) {
      connections[c]->updateState(sim_time, deltaTime);
      connections[c]->outputState(sim_time);
   }

   // Update the layers (activity)
   //
   for (int l = 0; l < numLayers; l++) {
      layers[l]->outputState(sim_time);

      // deliver new synaptic activity to layer
      //
      layers[l]->triggerReceive(icComm);

      // update layer and calculate new activity
      //
      layers[l]->updateState(sim_time, deltaTime);
   }

   // This loop separate from the update layer loop above
   // to provide time for layer data to be copied from
   // the OpenCL device.
   //
   for (int l = 0; l < numLayers; l++) {
      layers[l]->updateBorder(sim_time, deltaTime);

      // TODO - move this to layer
      // Advance time level so we have a new place in data store
      // to copy the data.  This should be done immediately before
      // publish so there is a place to publish and deliver the data to.
      // No one can access the data store (except to publish) until
      // wait has been called.  This should be fixed so that publish goes
      // to last time level and level is advanced only after wait.
      icComm->increaseTimeLevel(layers[l]->getLayerId());

      layers[l]->publish(icComm, sim_time);
   }

   // wait for all published data to arrive
   //
   for (int l = 0; l < numLayers; l++) {
      layers[l]->waitOnPublish(icComm);
   }

   // make sure simTime is updated even if HyPerCol isn't running time loop

   float outputTime = simTime; // so that outputState is called with the correct time
                               // but doesn't effect runTimer

   simTime = sim_time + deltaTime;

   runTimer->stop();

   outputState(outputTime);

   return simTime;
}

int HyPerCol::exitRunLoop(bool exitOnFinish)
{
   int status = 0;

   // output final state of layers and connections
   //
   bool last = true;

   for (int l = 0; l < numLayers; l++) {
      layers[l]->writeState(layers[l]->getName(), simTime, last);
   }

   for (int c = 0; c < numConnections; c++) {
      connections[c]->outputState(simTime, last);
   }

   if (exitOnFinish) {
      delete this;
      exit(0);
   }

   return status;
}

int HyPerCol::initializeThreads(int device)
{
   clDevice = new CLDevice(device);
   return 0;
}

int HyPerCol::finalizeThreads()
{
   delete clDevice;
   return 0;
}

int HyPerCol::loadState()
{
   return 0;
}

int HyPerCol::writeState()
{
   for (int l = 0; l < numLayers; l++) {
      layers[l]->writeState(OUTPUT_PATH, simTime);
   }
   return 0;
}

int HyPerCol::insertProbe(ColProbe * p)
{
   ColProbe ** newprobes;
   newprobes = (ColProbe **) malloc((numProbes + 1) * sizeof(ColProbe *));
   assert(newprobes != NULL);

   for (int i = 0; i < numProbes; i++) {
      newprobes[i] = probes[i];
   }
   delete probes;

   probes = newprobes;
   probes[numProbes] = p;

   return ++numProbes;
}

int HyPerCol::outputState(float time)
{
   for( int n = 0; n < numProbes; n++ ) {
       probes[n]->outputState(time, this);
   }
   return EXIT_SUCCESS;
}

int HyPerCol::checkMarginWidths() {
   // For each connection, make sure that the post-synaptic margin width is
   // large enough for the patch size.

   // TODO instead of having marginWidth supplied to HyPerLayers in the
   // params.pv file, calculate them based on the patch sizes here.
   // Hard part:  numExtended-sized quantities (e.g. clayer->activity) can't
   // be allocated and initialized until after nPad is determined.

   int status = EXIT_SUCCESS;
   int status1, status2;
   for( int c=0; c < numConnections; c++ ) {
      HyPerConn * conn = connections[c];
      int padding = conn->pre->getLayerLoc()->nb;

      int xScalePre = conn->preSynapticLayer()->getXScale();
      int xScalePost = conn->postSynapticLayer()->getXScale();
      status1 = zCheckMarginWidth(conn, "x", padding, conn->xPatchSize(), xScalePre, xScalePost, status);

      int yScalePre = conn->preSynapticLayer()->getYScale();
      int yScalePost = conn->postSynapticLayer()->getYScale();
      status2 = zCheckMarginWidth(conn, "y", padding, conn->yPatchSize(), yScalePre, yScalePost, status);
      status = (status == EXIT_SUCCESS && status1 == EXIT_SUCCESS && status2 == EXIT_SUCCESS) ?
               EXIT_SUCCESS : EXIT_FAILURE;
   }
   return status;
}  // end HyPerCol::checkMarginWidths()

int HyPerCol::zCheckMarginWidth(HyPerConn * conn, const char * dim, int padding, int patchSize, int scalePre, int scalePost, int prevStatus) {
   int status;
   int scaleDiff = scalePre - scalePost;
   // if post has higher neuronal density than pre, scaleDiff < 0.
   int needed = scaleDiff > 0 ? ( patchSize/( (int) powf(2,scaleDiff) )/2 ) :
                                ( (patchSize/2) * ( (int) powf(2,-scaleDiff) ) );
   if( padding < needed ) {
      if( prevStatus == EXIT_SUCCESS ) {
         fprintf(stderr, "Margin width error.\n");
      }
      fprintf(stderr, "Connection \"%s\", dimension %s:\n", conn->getName(), dim);
      fprintf(stderr, "    Margin width %d, patch size %d, presynaptic scale %d, postsynaptic scale %d\n",
              padding, patchSize, scalePre, scalePost);
      fprintf(stderr, "    Needed margin width=%d\n", needed);
      status = EXIT_FAILURE;
      if( numberOfColumns() > 1 || padding > 0 ) {
         fprintf(stderr, "Exiting.\n");
         exit(EXIT_FAILURE);
      }
      else {
         fprintf(stderr, "Continuing, but there may be undesirable edge effects.\n");
      }
   }
   else status = EXIT_SUCCESS;
   return status;
}

} // PV namespace
<commit_msg>Removed log_parameters (should probably be fixed).<commit_after>/*
 * HyPerCol.cpp
 *
 *  Created on: Jul 30, 2008
 *      Author: Craig Rasmussen
 */

#define TIMER_ON
#undef TIMESTEP_OUTPUT

#include "HyPerCol.hpp"
#include "InterColComm.hpp"
#include "../connections/PVConnection.h"
#include "../io/clock.h"
#include "../io/imageio.hpp"
#include "../io/io.h"
#include "../utils/pv_random.h"

#include <assert.h>
#include <math.h>
#include <memory.h>
#include <stdio.h>
#include <stdlib.h>

namespace PV {

HyPerCol::HyPerCol(const char * name, int argc, char * argv[])
         : warmStart(false), isInitialized(false)
{
   int opencl_device = 1;  // default to CPU for now

   // TODO - fix these numbers to dynamically grow
   maxLayers = MAX_LAYERS;
   maxConnections = MAX_CONNECTIONS;

   this->name = strdup(name);
   this->runTimer = new Timer();

   char * param_file;
   simTime = 0;
   numLayers = 0;
   numConnections = 0;
   layers = (HyPerLayer **) malloc(maxLayers * sizeof(HyPerLayer *));
   connections = (HyPerConn **) malloc(maxConnections * sizeof(HyPerConn *));

   numSteps = 2;
   image_file = NULL;
   param_file = NULL;
   unsigned long random_seed = 0;
   parse_options(argc, argv, &image_file, &param_file, &numSteps, &opencl_device, &random_seed);

   // run only on CPU for now
   initializeThreads(opencl_device);

   // estimate for now
   // TODO -get rid of maxGroups
   int maxGroups = 2*(maxLayers + maxConnections);
   params = new PVParams(param_file, maxGroups);

   icComm = new InterColComm(&argc, &argv);

   // initialize random seed
   //
   random_seed = getRandomSeed();
   random_seed = params->value(name, "randomSeed", random_seed);
   pv_srandom(random_seed);

   if (param_file != NULL) free(param_file);

   deltaTime = DELTA_T;
   if (params->present(name, "dt")) deltaTime = params->value(name, "dt");

   int status = -1;
   if (image_file) {
      status = getImageInfo(image_file, icComm, &imageLoc);
   }

   if (status) {
      imageLoc.nxGlobal = (int) params->value(name, "nx");
      imageLoc.nyGlobal = (int) params->value(name, "ny");

      // set loc based on global parameters and processor partitioning
      //
      setLayerLoc(&imageLoc, 1.0f, 1.0f, 0, 1);
   }

   runDelegate = NULL;

   numProbes = 0;
   probes = NULL;
}

HyPerCol::~HyPerCol()
{
   int n;

   finalizeThreads();

   if (image_file != NULL) free(image_file);

   for (n = 0; n < numConnections; n++) {
      delete connections[n];
   }

   for (n = 0; n < numLayers; n++) {
      // TODO: check to see if finalize called
      if (layers[n] != NULL) {
         delete layers[n]; // will call *_finalize
      }
      else {
         // TODO move finalize
         // PVLayer_finalize(getCLayer(n));
      }
   }

   delete icComm;

   printf("%16s: total time in %6s %10s: ", name, "column", "run");
   runTimer->elapsed_time();
   delete runTimer;

   free(connections);
   free(layers);
   free(name);
}

int HyPerCol::initFinish(void)
{
   int status = 0;

   for (int i = 0; i < this->numLayers; i++) {
      status = layers[i]->initFinish();
      if (status != 0) {
         fprintf(stderr, "[%d]: HyPerCol::initFinish: ERROR condition, exiting...\n", this->columnId());
         exit(status);
      }
   }

#ifdef OBSOLETE
   // TODO - fix this to modern version?
   log_parameters(numSteps, image_file);
#endif

   isInitialized = true;

   return status;
}

int HyPerCol::columnId()
{
   return icComm->commRank();
}

int HyPerCol::numberOfColumns()
{
   return icComm->numCommRows() * icComm->numCommColumns();
}

int HyPerCol::commColumn(int colId)
{
   return colId % icComm->numCommColumns();
}

int HyPerCol::commRow(int colId)
{
   return colId / icComm->numCommColumns();
}

int HyPerCol::setLayerLoc(PVLayerLoc * layerLoc,
                          float nxScale, float nyScale, int margin, int nf)
{
   layerLoc->nxGlobal = (int) (nxScale * imageLoc.nxGlobal);
   layerLoc->nyGlobal = (int) (nyScale * imageLoc.nyGlobal);

   // partition input space based on the number of processor
   // columns and rows
   //

   layerLoc->nx = layerLoc->nxGlobal / icComm->numCommColumns();
   layerLoc->ny = layerLoc->nyGlobal / icComm->numCommRows();

   assert(layerLoc->nxGlobal == layerLoc->nx * icComm->numCommColumns());
   assert(layerLoc->nyGlobal == layerLoc->ny * icComm->numCommRows());

   layerLoc->kx0 = layerLoc->nx * icComm->commColumn();
   layerLoc->ky0 = layerLoc->ny * icComm->commRow();

   layerLoc->nf = nf;
   layerLoc->nb = margin;

   layerLoc->halo.lt = margin;
   layerLoc->halo.rt = margin;
   layerLoc->halo.dn = margin;
   layerLoc->halo.up = margin;

   return 0;
}

int HyPerCol::addLayer(HyPerLayer * l)
{
   assert(numLayers < maxLayers);
   l->columnWillAddLayer(icComm, numLayers);
   layers[numLayers++] = l;
   return (numLayers - 1);
}

int HyPerCol::addConnection(HyPerConn * conn)
{
   int connId = numConnections;

   assert(numConnections < maxConnections);

   // numConnections is the ID of this connection
   icComm->subscribe(conn);

   connections[numConnections++] = conn;

   return connId;
}

int HyPerCol::run(int nTimeSteps)
{
   checkMarginWidths();

   int step = 0;
   float stopTime = simTime + nTimeSteps * deltaTime;
   const bool exitOnFinish = false;

   if (!isInitialized) {
      initFinish();
   }

   numSteps = nTimeSteps;

#ifdef DEBUG_OUTPUT
   if (columnId() == 0) {
      printf("[0]: HyPerCol: running...\n");  fflush(stdout);
   }
#endif

   // publish initial conditions
   //
   for (int l = 0; l < numLayers; l++) {
      layers[l]->publish(icComm, simTime);
   }

   // wait for all published data to arrive
   //
   for (int l = 0; l < numLayers; l++) {
      icComm->wait(layers[l]->getLayerId());
   }

   if (runDelegate) {
      // let delegate advance the time
      //
      runDelegate->run(simTime, stopTime);
   }

#ifdef TIMER_ON
      start_clock();
#endif
   // time loop
   //
   while (simTime < stopTime) {
      simTime = advanceTime(simTime);
      step += 1;

#ifdef TIMER_ON
      if (step == 10) start_clock();
#endif

   }  // end time loop

#ifdef DEBUG_OUTPUT
   if (columnId() == 0) {
      printf("[0]: HyPerCol::run done...\n");  fflush(stdout);
   }
#endif

   exitRunLoop(exitOnFinish);

#ifdef TIMER_ON
      stop_clock();
#endif

   return 0;
}

float HyPerCol::advanceTime(float sim_time)
{
#ifdef TIMESTEP_OUTPUT
   int nstep = (int) (sim_time/getDeltaTime());
   if (nstep%2000 == 0 && columnId() == 0) {
      printf("   [%d]: time==%f\n", columnId(), sim_time);
   }
#endif

   runTimer->start();

   // At this point all activity from the previous time step have
   // been delivered to the data store.
   //

   // update the connections (weights)
   //
   for (int c = 0; c < numConnections; c++) {
      connections[c]->updateState(sim_time, deltaTime);
      connections[c]->outputState(sim_time);
   }

   // Update the layers (activity)
   //
   for (int l = 0; l < numLayers; l++) {
      layers[l]->outputState(sim_time);

      // deliver new synaptic activity to layer
      //
      layers[l]->triggerReceive(icComm);

      // update layer and calculate new activity
      //
      layers[l]->updateState(sim_time, deltaTime);
   }

   // This loop separate from the update layer loop above
   // to provide time for layer data to be copied from
   // the OpenCL device.
   //
   for (int l = 0; l < numLayers; l++) {
      layers[l]->updateBorder(sim_time, deltaTime);

      // TODO - move this to layer
      // Advance time level so we have a new place in data store
      // to copy the data.  This should be done immediately before
      // publish so there is a place to publish and deliver the data to.
      // No one can access the data store (except to publish) until
      // wait has been called.  This should be fixed so that publish goes
      // to last time level and level is advanced only after wait.
      icComm->increaseTimeLevel(layers[l]->getLayerId());

      layers[l]->publish(icComm, sim_time);
   }

   // wait for all published data to arrive
   //
   for (int l = 0; l < numLayers; l++) {
      layers[l]->waitOnPublish(icComm);
   }

   // make sure simTime is updated even if HyPerCol isn't running time loop

   float outputTime = simTime; // so that outputState is called with the correct time
                               // but doesn't effect runTimer

   simTime = sim_time + deltaTime;

   runTimer->stop();

   outputState(outputTime);

   return simTime;
}

int HyPerCol::exitRunLoop(bool exitOnFinish)
{
   int status = 0;

   // output final state of layers and connections
   //
   bool last = true;

   for (int l = 0; l < numLayers; l++) {
      layers[l]->writeState(layers[l]->getName(), simTime, last);
   }

   for (int c = 0; c < numConnections; c++) {
      connections[c]->outputState(simTime, last);
   }

   if (exitOnFinish) {
      delete this;
      exit(0);
   }

   return status;
}

int HyPerCol::initializeThreads(int device)
{
   clDevice = new CLDevice(device);
   return 0;
}

int HyPerCol::finalizeThreads()
{
   delete clDevice;
   return 0;
}

int HyPerCol::loadState()
{
   return 0;
}

int HyPerCol::writeState()
{
   for (int l = 0; l < numLayers; l++) {
      layers[l]->writeState(OUTPUT_PATH, simTime);
   }
   return 0;
}

int HyPerCol::insertProbe(ColProbe * p)
{
   ColProbe ** newprobes;
   newprobes = (ColProbe **) malloc((numProbes + 1) * sizeof(ColProbe *));
   assert(newprobes != NULL);

   for (int i = 0; i < numProbes; i++) {
      newprobes[i] = probes[i];
   }
   delete probes;

   probes = newprobes;
   probes[numProbes] = p;

   return ++numProbes;
}

int HyPerCol::outputState(float time)
{
   for( int n = 0; n < numProbes; n++ ) {
       probes[n]->outputState(time, this);
   }
   return EXIT_SUCCESS;
}

int HyPerCol::checkMarginWidths() {
   // For each connection, make sure that the post-synaptic margin width is
   // large enough for the patch size.

   // TODO instead of having marginWidth supplied to HyPerLayers in the
   // params.pv file, calculate them based on the patch sizes here.
   // Hard part:  numExtended-sized quantities (e.g. clayer->activity) can't
   // be allocated and initialized until after nPad is determined.

   int status = EXIT_SUCCESS;
   int status1, status2;
   for( int c=0; c < numConnections; c++ ) {
      HyPerConn * conn = connections[c];
      int padding = conn->pre->getLayerLoc()->nb;

      int xScalePre = conn->preSynapticLayer()->getXScale();
      int xScalePost = conn->postSynapticLayer()->getXScale();
      status1 = zCheckMarginWidth(conn, "x", padding, conn->xPatchSize(), xScalePre, xScalePost, status);

      int yScalePre = conn->preSynapticLayer()->getYScale();
      int yScalePost = conn->postSynapticLayer()->getYScale();
      status2 = zCheckMarginWidth(conn, "y", padding, conn->yPatchSize(), yScalePre, yScalePost, status);
      status = (status == EXIT_SUCCESS && status1 == EXIT_SUCCESS && status2 == EXIT_SUCCESS) ?
               EXIT_SUCCESS : EXIT_FAILURE;
   }
   return status;
}  // end HyPerCol::checkMarginWidths()

int HyPerCol::zCheckMarginWidth(HyPerConn * conn, const char * dim, int padding, int patchSize, int scalePre, int scalePost, int prevStatus) {
   int status;
   int scaleDiff = scalePre - scalePost;
   // if post has higher neuronal density than pre, scaleDiff < 0.
   int needed = scaleDiff > 0 ? ( patchSize/( (int) powf(2,scaleDiff) )/2 ) :
                                ( (patchSize/2) * ( (int) powf(2,-scaleDiff) ) );
   if( padding < needed ) {
      if( prevStatus == EXIT_SUCCESS ) {
         fprintf(stderr, "Margin width error.\n");
      }
      fprintf(stderr, "Connection \"%s\", dimension %s:\n", conn->getName(), dim);
      fprintf(stderr, "    Margin width %d, patch size %d, presynaptic scale %d, postsynaptic scale %d\n",
              padding, patchSize, scalePre, scalePost);
      fprintf(stderr, "    Needed margin width=%d\n", needed);
      status = EXIT_FAILURE;
      if( numberOfColumns() > 1 || padding > 0 ) {
         fprintf(stderr, "Exiting.\n");
         exit(EXIT_FAILURE);
      }
      else {
         fprintf(stderr, "Continuing, but there may be undesirable edge effects.\n");
      }
   }
   else status = EXIT_SUCCESS;
   return status;
}

} // PV namespace
<|endoftext|>


<commit_before>#include <command/command.hpp>
#include <server.hpp>
#include <singleton.hpp>
#include <utility>

using namespace MCPP;

namespace MCPP {

	static const Word priority=2;
	static const String name("Command Support");

	//	Precedes all help output
	static const String help_banner("====HELP====");
	//	Prefix that precedes commands
	static const String prefix("/");
	//	Separates command from its summary in help
	static const String summary_separator(" - ");
	//	Starts off the chat message that's sent when
	//	incorrect syntax is used
	static const String incorrect_syntax_label("Incorrect syntax");
	//	Introduces "/help" in incorrect syntax strings
	static const String try_label(" try ");
	//	The identifier for the help command
	static const String help_identifier("help");
	//	A space
	static const String separator(" ");
	//	Informs the user that they are not permitted
	//	to execute a command
	static const String not_permitted("You are not permitted to do that");
	//	Informs the user that a command they attempted
	//	to execute does not exist
	static const String does_not_exist("Command does not exist");
	//	Gives help with the help command
	static const String help_help("For help with a specific command type ");
	//	The syntax of the help command is /help and then this
	static const String help_syntax("<command>");

	//	Parses a command
	static const Regex parse("^\\/(\\S*)(?:\\s*(.*))?$");
	//	Splits the arguments to a command
	//	on whitespace
	static const Regex split("(?<=\\s|^)\\S+(?=\\s|$)");
	//	Checks to see if there's trailing whitespace
	static const Regex trailing_whitespace("\\s$");

	Command * Commands::get (const String & identifier) {

		auto iter=map.find(identifier);

		return (iter==map.end()) ? nullptr : iter->second;

	}

	ChatMessage Commands::incorrect_syntax () {

		ChatMessage retr;
		retr	<<	ChatStyle::Red
				<<	ChatStyle::Bold
				<<	incorrect_syntax_label
				<<	ChatFormat::Pop
				<<	try_label
				<<	ChatStyle::Bold
				<<	prefix
				<<	help_identifier;

		return retr;

	}

	ChatMessage Commands::incorrect_syntax (const String & identifier) {

		auto retr=incorrect_syntax();

		retr << separator << identifier;

		return retr;

	}

	ChatMessage Commands::command_dne () {

		ChatMessage retr;
		retr	<<	ChatStyle::Red
				<<	ChatStyle::Bold
				<<	does_not_exist;

		return retr;

	}

	ChatMessage Commands::insufficient_privileges () {

		ChatMessage retr;
		retr	<<	ChatStyle::Red
				<<	ChatStyle::Bold
				<<	not_permitted;

		return retr;

	}

	ChatMessage Commands::help (CommandEvent event) {

		ChatMessage retr;
		retr	<<	ChatStyle::Yellow
				<<	ChatStyle::Bold
				<<	help_banner
				<<	ChatFormat::Pop
				<<	Newline;

		if (event.Arguments.Count()==0) {

			//	If there are no arguments, we retrieve
			//	a listing and summary of all commands

			retr	<<	help_help
					<<	ChatStyle::Bold
					<<	prefix
					<<	help_identifier
					<<	separator
					<<	help_syntax
					<<	ChatFormat::Pop		//	Get rid of bold
					<<	ChatFormat::Pop;	//	Get rid of yellow (from above)

			//	Loop and only show user commands that
			//	they are permitted to use
			for (const auto & c : list) {

				event.Identifier=c.Item<0>();

				if (c.Item<1>()->Check(event)) {

					retr	<<	Newline
							<<	ChatStyle::Bold
							<<	prefix
							<<	c.Item<0>()
							<<	ChatFormat::Pop
							<<	summary_separator;

					c.Item<1>()->Summary(c.Item<0>(),retr);

				}

			}

		} else if (event.Arguments.Count()==1) {

			//	Attempt to find and deliver help specific
			//	to this command

			event.Identifier=event.Arguments[0];
			auto command=get(event.Identifier);

			//	Make sure command exists
			if (command==nullptr) return command_dne();

			//	Make sure user can view this command
			if (!command->Check(event)) return insufficient_privileges();

			//	Output
			retr	<<	ChatStyle::Bold
					<<	prefix
					<<	event.Identifier
					<<	ChatFormat::Pop	//	Get rid of bold
					<<	ChatFormat::Pop	//	Get rid of yellow (from above)
					<<	Newline;

			command->Help(event.Identifier,retr);

		} else {

			//	If there is more than one argument,
			//	that's an error
			return incorrect_syntax();

		}

		return retr;

	}

	Nullable<CommandEvent> Commands::parse (SmartPointer<Client> client, const String & str, bool keep_trailing) {

		Nullable<CommandEvent> retr;

		//	If it's not actually a command, return
		//	at once
		auto match=::parse.Match(str);
		if (!match.Success()) return retr;

		//	Split the arguments
		auto raw_args=match[2].Value();
		auto matches=split.Matches(raw_args);
		Vector<String> args;
		for (auto & match : matches) args.Add(match.Value());

		//	If we're keeping trailing whitespace, check
		//	for it
		if (
			keep_trailing &&
			trailing_whitespace.IsMatch(str)
		) args.EmplaceBack();

		retr=CommandEvent{
			std::move(client),
			match[1].Value(),
			std::move(args),
			str,
			std::move(raw_args)
		};

		return retr;

	}

	Nullable<ChatMessage> Commands::execute (SmartPointer<Client> client, const String & str) {

		Nullable<ChatMessage> retr;

		//	Attempt to parse the command
		auto event=parse(
			std::move(client),
			str
		);

		//	If the parse failed, it's not
		//	actually a command
		if (event.IsNull()) return retr;

		//	Is it the help command?
		if (event->Identifier==help_identifier) {

			retr=help(std::move(*event));

			return retr;

		}

		//	Attempt to look up this command
		auto command=get(event->Identifier);

		//	If there's no such command, return that
		if (command==nullptr) {

			retr=command_dne();

			return retr;

		}

		//	Ensure command processing should proceed
		if (!command->Check(*event)) {

			retr=insufficient_privileges();

			return retr;

		}

		//	Save the identifier -- we'll need it if
		//	the syntax is incorrect
		auto identifier=event->Identifier;

		//	Otherwise execute the command
		auto result=command->Execute(std::move(*event));

		switch (result.Status) {

			case CommandStatus::Success:
				retr=std::move(result.Message);
				break;
			case CommandStatus::SyntaxError:
			default:
				retr=incorrect_syntax(identifier);
				break;
			case CommandStatus::DoesNotExist:
				retr=command_dne();
				break;
			case CommandStatus::Forbidden:
				retr=insufficient_privileges();
				break;

		}

		return retr;

	}

	Vector<String> Commands::auto_complete (SmartPointer<Client> client, const String & str) {

		Vector<String> retr;

		//	Parse
		auto event=parse(
			std::move(client),
			str,
			true
		);

		//	If the parse failed, return at once
		if (event.IsNull()) return retr;

		//	If the parse actually extracted a full
		//	command identifier, we try and find that
		//	command to get auto completions, otherwise
		//	we try and autocomplete to a command
		//	identifier

		if (event->Arguments.Count()==0) {

			//	Construct a regular expression which
			//	matches the stem the user gave
			Regex regex(
				String::Format(
					"^{0}",
					Regex::Escape(event->Identifier)
				)
			);

			//	Loop over each command and create list
			//	of suggestions based on matches
			for (const auto & t : list) if (
				regex.IsMatch(t.Item<0>()) &&
				//	Make sure this user can actually run
				//	this command
				t.Item<1>()->Check(*event)
			) retr.Add(t.Item<0>());

		} else {

			//	Attempt to get command
			auto command=get(event->Identifier);

			if (
				//	If the command could not be found,
				//	return at once
				(command==nullptr) ||
				//	If the user can't actually execute the
				//	command, return at once
				!command->Check(*event)
			) return retr;

			//	Get auto completions
			retr=command->AutoComplete(*event);

		}

		return retr;

	}

	static Singleton<Commands> singleton;

	Commands & Commands::Get () noexcept {

		return singleton.Get();

	}

	const String & Commands::Name () const noexcept {

		return name;

	}

	Word Commands::Priority () const noexcept {

		return priority;

	}

	void Commands::Install () {

		typedef Packets::Play::Clientbound::TabComplete reply;
		typedef Packets::Play::Serverbound::TabComplete request;

		//	Install auto complete handler
		Server::Get().Router(
			request::PacketID,
			request::State
		)=[this] (PacketEvent event) mutable {

			auto packet=event.Data.Get<request>();

			reply p;
			p.Match=auto_complete(event.From,packet.Text);

			event.From->Send(p);

		};

		//	Install chat handler

		auto & chat=Chat::Get();

		//	Save previous handler
		auto prev=std::move(chat.Chat);

		//	Install new handler
		#pragma GCC diagnostic push
		#pragma GCC diagnostic ignored "-Wpedantic"
		chat.Chat=[this,prev=std::move(prev)] (ChatEvent event) mutable {

			//	Attempt to execute as a command
			auto result=execute(event.From,event.Body);

			if (result.IsNull()) {

				//	If parsing/execution fails, attempt
				//	to pass through
				if (prev) prev(std::move(event));

			//	Sending empty messages crashes client
			} else if (result->Message.Count()!=0) {

				//	If parsing/execute succeeds, send
				//	response

				result->Recipients.Add(std::move(event.From));

				Chat::Get().Send(*result);

			}

		};
		#pragma GCC diagnostic pop

	}

	Nullable<String> Commands::operator () (const String & str) {

		Nullable<String> retr;

		auto result=execute(
			SmartPointer<Client>(),
			str
		);

		if (!result.IsNull()) retr=Chat::ToString(*result);

		return retr;

	}

	void Commands::Add (String identifier, Command * command) {

		//	Don't proceed with adding null pointers
		if (command==nullptr) return;

		//	Find insertion point in vector
		Word loc=0;
		for (
			;
			(loc<list.Count()) &&
			(list[loc].Item<0>()<identifier);
			++loc
		);

		//	Delete duplicate command if
		//	present
		auto iter=map.find(identifier);
		if (iter!=map.end()) {

			map.erase(iter);
			list.Delete(loc);

		}

		//	Add
		list.Emplace(
			loc,
			identifier,
			command
		);
		try {

			map.emplace(
				std::move(identifier),
				command
			);

		} catch (...) {

			//	Roll back on throw

			list.Delete(loc);

			throw;

		}

	}

}

extern "C" {

	Module * Load () {

		return &(Commands::Get());

	}

	void Unload () {

		singleton.Destroy();

	}

}
<commit_msg>Commands Fixes<commit_after>#include <command/command.hpp>
#include <server.hpp>
#include <singleton.hpp>
#include <utility>

using namespace MCPP;

namespace MCPP {

	static const Word priority=2;
	static const String name("Command Support");

	//	Precedes all help output
	static const String help_banner("====HELP====");
	//	Prefix that precedes commands
	static const String prefix("/");
	//	Separates command from its summary in help
	static const String summary_separator(" - ");
	//	Starts off the chat message that's sent when
	//	incorrect syntax is used
	static const String incorrect_syntax_label("Incorrect syntax");
	//	Introduces "/help" in incorrect syntax strings
	static const String try_label(" try ");
	//	The identifier for the help command
	static const String help_identifier("help");
	//	A space
	static const String separator(" ");
	//	Informs the user that they are not permitted
	//	to execute a command
	static const String not_permitted("You are not permitted to do that");
	//	Informs the user that a command they attempted
	//	to execute does not exist
	static const String does_not_exist("Command does not exist");
	//	Gives help with the help command
	static const String help_help("For help with a specific command type ");
	//	The syntax of the help command is /help and then this
	static const String help_syntax("<command>");

	//	Parses a command
	static const Regex parse("^\\/(\\S*)(?:\\s*(.*))?$");
	//	Splits the arguments to a command
	//	on whitespace
	static const Regex split("(?<=\\s|^)\\S+(?=\\s|$)");
	//	Checks to see if there's trailing whitespace
	static const Regex trailing_whitespace("\\s$");

	Command * Commands::get (const String & identifier) {

		auto iter=map.find(identifier);

		return (iter==map.end()) ? nullptr : iter->second;

	}

	ChatMessage Commands::incorrect_syntax () {

		ChatMessage retr;
		retr	<<	ChatStyle::Red
				<<	ChatStyle::Bold
				<<	incorrect_syntax_label
				<<	ChatFormat::Pop
				<<	try_label
				<<	ChatStyle::Bold
				<<	prefix
				<<	help_identifier;

		return retr;

	}

	ChatMessage Commands::incorrect_syntax (const String & identifier) {

		auto retr=incorrect_syntax();

		retr << separator << identifier;

		return retr;

	}

	ChatMessage Commands::command_dne () {

		ChatMessage retr;
		retr	<<	ChatStyle::Red
				<<	ChatStyle::Bold
				<<	does_not_exist;

		return retr;

	}

	ChatMessage Commands::insufficient_privileges () {

		ChatMessage retr;
		retr	<<	ChatStyle::Red
				<<	ChatStyle::Bold
				<<	not_permitted;

		return retr;

	}

	ChatMessage Commands::help (CommandEvent event) {

		ChatMessage retr;
		retr	<<	ChatStyle::Yellow
				<<	ChatStyle::Bold
				<<	help_banner
				<<	ChatFormat::Pop
				<<	Newline;

		if (event.Arguments.Count()==0) {

			//	If there are no arguments, we retrieve
			//	a listing and summary of all commands

			retr	<<	help_help
					<<	ChatStyle::Bold
					<<	prefix
					<<	help_identifier
					<<	separator
					<<	help_syntax
					<<	ChatFormat::Pop		//	Get rid of bold
					<<	ChatFormat::Pop;	//	Get rid of yellow (from above)

			//	Loop and only show user commands that
			//	they are permitted to use
			for (const auto & c : list) {

				event.Identifier=c.Item<0>();

				if (c.Item<1>()->Check(event)) {

					retr	<<	Newline
							<<	ChatStyle::Bold
							<<	prefix
							<<	c.Item<0>()
							<<	ChatFormat::Pop
							<<	summary_separator;

					c.Item<1>()->Summary(c.Item<0>(),retr);

				}

			}

		} else if (event.Arguments.Count()==1) {

			//	Attempt to find and deliver help specific
			//	to this command

			event.Identifier=event.Arguments[0];
			auto command=get(event.Identifier);

			//	Make sure command exists
			if (command==nullptr) return command_dne();

			//	Make sure user can view this command
			if (!command->Check(event)) return insufficient_privileges();

			//	Output
			retr	<<	ChatStyle::Bold
					<<	prefix
					<<	event.Identifier
					<<	ChatFormat::Pop	//	Get rid of bold
					<<	ChatFormat::Pop	//	Get rid of yellow (from above)
					<<	Newline;

			command->Help(event.Identifier,retr);

		} else {

			//	If there is more than one argument,
			//	that's an error
			return incorrect_syntax();

		}

		return retr;

	}

	Nullable<CommandEvent> Commands::parse (SmartPointer<Client> client, const String & str, bool keep_trailing) {

		Nullable<CommandEvent> retr;

		//	If it's not actually a command, return
		//	at once
		auto match=::parse.Match(str);
		if (!match.Success()) return retr;

		//	Split the arguments
		auto raw_args=match[2].Value();
		auto matches=split.Matches(raw_args);
		Vector<String> args;
		for (auto & match : matches) args.Add(match.Value());

		//	If we're keeping trailing whitespace, check
		//	for it
		if (
			keep_trailing &&
			trailing_whitespace.IsMatch(str)
		) args.EmplaceBack();

		retr=CommandEvent{
			std::move(client),
			match[1].Value(),
			std::move(args),
			str,
			std::move(raw_args)
		};

		return retr;

	}

	Nullable<ChatMessage> Commands::execute (SmartPointer<Client> client, const String & str) {

		Nullable<ChatMessage> retr;

		//	Attempt to parse the command
		auto event=parse(
			std::move(client),
			str
		);

		//	If the parse failed, it's not
		//	actually a command
		if (event.IsNull()) return retr;

		//	Is it the help command?
		if (event->Identifier==help_identifier) {

			retr=help(std::move(*event));

			return retr;

		}

		//	Attempt to look up this command
		auto command=get(event->Identifier);

		//	If there's no such command, return that
		if (command==nullptr) {

			retr=command_dne();

			return retr;

		}

		//	Ensure command processing should proceed
		if (!command->Check(*event)) {

			retr=insufficient_privileges();

			return retr;

		}

		//	Save the identifier -- we'll need it if
		//	the syntax is incorrect
		auto identifier=event->Identifier;

		//	Otherwise execute the command
		auto result=command->Execute(std::move(*event));

		switch (result.Status) {

			case CommandStatus::Success:
				retr=std::move(result.Message);
				break;
			case CommandStatus::SyntaxError:
			default:
				retr=incorrect_syntax(identifier);
				break;
			case CommandStatus::DoesNotExist:
				retr=command_dne();
				break;
			case CommandStatus::Forbidden:
				retr=insufficient_privileges();
				break;

		}

		return retr;

	}

	Vector<String> Commands::auto_complete (SmartPointer<Client> client, const String & str) {

		Vector<String> retr;

		//	Parse
		auto event=parse(
			std::move(client),
			str,
			true
		);

		//	If the parse failed, return at once
		if (event.IsNull()) return retr;

		//	If the parse actually extracted a full
		//	command identifier, we try and find that
		//	command to get auto completions, otherwise
		//	we try and autocomplete to a command
		//	identifier

		if (event->Arguments.Count()==0) {

			//	Construct a regular expression which
			//	matches the stem the user gave
			Regex regex(
				String::Format(
					"^{0}",
					Regex::Escape(event->Identifier)
				)
			);

			//	Loop over each command and create list
			//	of suggestions based on matches
			for (const auto & t : list) if (
				regex.IsMatch(t.Item<0>()) &&
				//	Make sure this user can actually run
				//	this command
				t.Item<1>()->Check(*event)
			) retr.Add(t.Item<0>());

		} else {

			//	Attempt to get command
			auto command=get(event->Identifier);

			if (
				//	If the command could not be found,
				//	return at once
				(command==nullptr) ||
				//	If the user can't actually execute the
				//	command, return at once
				!command->Check(*event)
			) return retr;

			//	Get auto completions
			retr=command->AutoComplete(*event);

		}

		return retr;

	}

	static Singleton<Commands> singleton;

	Commands & Commands::Get () noexcept {

		return singleton.Get();

	}

	const String & Commands::Name () const noexcept {

		return name;

	}

	Word Commands::Priority () const noexcept {

		return priority;

	}

	void Commands::Install () {

		typedef Packets::Play::Clientbound::TabComplete reply;
		typedef Packets::Play::Serverbound::TabComplete request;

		auto & server=Server::Get();

		//	Install auto complete handler
		server.Router(
			request::PacketID,
			request::State
		)=[this] (PacketEvent event) mutable {

			auto packet=event.Data.Get<request>();

			reply p;
			p.Match=auto_complete(event.From,packet.Text);

			event.From->Send(p);

		};

		//	Install chat handler

		auto & chat=Chat::Get();

		//	Save previous handler
		auto prev=std::move(chat.Chat);

		//	Install new handler
		#pragma GCC diagnostic push
		#pragma GCC diagnostic ignored "-Wpedantic"
		chat.Chat=[this,prev=std::move(prev)] (ChatEvent event) mutable {

			//	Attempt to execute as a command
			auto result=execute(event.From,event.Body);

			if (result.IsNull()) {

				//	If parsing/execution fails, attempt
				//	to pass through
				if (prev) prev(std::move(event));

			//	Sending empty messages crashes client
			} else if (result->Message.Count()!=0) {

				//	If parsing/execute succeeds, send
				//	response

				result->Recipients.Add(std::move(event.From));

				Chat::Get().Send(*result);

			}

		};
		#pragma GCC diagnostic pop

		//	Install as command interpreter into
		//	the server
		server.SetCommandInterpreter(this);

	}

	Nullable<String> Commands::operator () (const String & str) {

		Nullable<String> retr;

		auto result=execute(
			SmartPointer<Client>(),
			String("/")+str
		);

		if (!result.IsNull()) retr=Chat::ToString(*result);

		return retr;

	}

	void Commands::Add (String identifier, Command * command) {

		//	Don't proceed with adding null pointers
		if (command==nullptr) return;

		//	Find insertion point in vector
		Word loc=0;
		for (
			;
			(loc<list.Count()) &&
			(list[loc].Item<0>()<identifier);
			++loc
		);

		//	Delete duplicate command if
		//	present
		auto iter=map.find(identifier);
		if (iter!=map.end()) {

			map.erase(iter);
			list.Delete(loc);

		}

		//	Add
		list.Emplace(
			loc,
			identifier,
			command
		);
		try {

			map.emplace(
				std::move(identifier),
				command
			);

		} catch (...) {

			//	Roll back on throw

			list.Delete(loc);

			throw;

		}

	}

}

extern "C" {

	Module * Load () {

		return &(Commands::Get());

	}

	void Unload () {

		singleton.Destroy();

	}

}
<|endoftext|>


<commit_before>// This file is distributed under the MIT license.
// See the LICENSE file for details.

#include <cassert>
#include <cstddef>
#include <cstdint>
#include <fstream>
#include <string>

#if 1//ndef NDEBUG
#include <iostream>
#include <ostream>
#endif

#include <boost/algorithm/string.hpp>

#include "pnm_image.h"

namespace visionaray
{

//-------------------------------------------------------------------------------------------------
// Helper functions
//

static void load_binary_rgb(
        uint8_t*        dst,
        std::ifstream&  file,
        size_t          width,
        size_t          height,
        int             /*max_value*/
        )
{
//  assert(max_value < 256);    // TODO: 16-bit
//  assert(max_value == 255);   // TODO: scaling

    size_t pitch = width * 3;
    file.read(reinterpret_cast<char*>(dst), pitch * height);
}

//-------------------------------------------------------------------------------------------------
// pnm_image
//

bool pnm_image::load(std::string const& filename)
{
    enum format { P1 = 1, P2, P3, P4, P5, P6 };

    std::ifstream file(filename);

    std::string line;

    //
    // First line determines format:
    // P1: ASCII BW         | P4: binary BW
    // P2: ASCII gray scale | P5: binary gray scale
    // P3: ASCII RGB        | P6: binary RGB
    //
    std::getline(file, line);

    if (line.size() < 2 || line[0] != 'P' || line[1] < '0' || line[1] > '6')
    {
        std::cerr << "Invalid file format: " << line << '\n';
        return false;
    }

    format fmt = static_cast<format>(line[1] - '0');

    // Width and height
    for (;;)
    {
        std::getline(file, line);

        if (line[0] == '#')
        {
            // Skip comments
            continue;
        }
        else
        {
            std::vector<std::string> tokens;
            boost::algorithm::split(
                    tokens,
                    line,
                    boost::algorithm::is_any_of(" \t")
                    );

            if (tokens.size() != 2)
            {
                std::cerr << "Invalid dimensions\n";
                return false;
            }

            width_  = static_cast<size_t>(std::stoi(tokens[0]));
            height_ = static_cast<size_t>(std::stoi(tokens[1]));

            break;
        }
    }

    // Max. value
    int max_value = 255;
    if (fmt != P1 && fmt != P4)
    {
        for (;;)
        {
            std::getline(file, line);

            if (line[0] == '#')
            {
                // Skip comments
                continue;
            }
            else
            {
                max_value = std::stoi(line);
                break;
            }
        }
    }

    switch (fmt)
    {
    default:
        std::cerr << "Unsupported PNM image type: P" << std::to_string(static_cast<int>(fmt)) << '\n';
        width_  = 0;
        height_ = 0;
        format_ = PF_UNSPECIFIED;
        data_.resize(0);
        return false;

    case P6:
        assert(max_value < 256);
        assert(max_value == 255);
        format_ = PF_RGB8;
        data_.resize(width_ * height_ * 3);

        load_binary_rgb(
                data_.data(),
                file,
                width_,
                height_,
                max_value
                );
        return true;
    }

    return true;
}

}
<commit_msg>Support for ascii-rgb ppm images (P3)<commit_after>// This file is distributed under the MIT license.
// See the LICENSE file for details.

#include <algorithm>
#include <cassert>
#include <cctype>
#include <cstddef>
#include <cstdint>
#include <fstream>
#include <string>
#include <vector>

#if 1//ndef NDEBUG
#include <iostream>
#include <ostream>
#endif

#include <boost/algorithm/string.hpp>

#include "pnm_image.h"

namespace visionaray
{

//-------------------------------------------------------------------------------------------------
// Helper functions
//

static void load_ascii_rgb(
        uint8_t*        dst,
        std::ifstream&  file,
        size_t          width,
        size_t          height,
        int             /*max_value*/
        )
{
//  assert(max_value < 256);    // TODO: 16-bit
//  assert(max_value == 255);   // TODO: scaling

    for (size_t y = 0; y < height; ++y)
    {
        std::string line;
        std::getline(file, line);

        std::vector<std::string> tokens;
        boost::algorithm::split(
                tokens,
                line,
                boost::algorithm::is_any_of(" \t")
                );

        // Remove empty tokens and  spaces
        tokens.erase(
                std::remove_if(
                        tokens.begin(),
                        tokens.end(),
                        [](std::string str) { return str.empty() || std::isspace(str[0]); }
                        ),
                tokens.end()
                );

        size_t pitch = width * 3;
        assert(tokens.size() == pitch);

        for (size_t x = 0; x < pitch; ++x)
        {
            dst[y * pitch + x] = static_cast<uint8_t>(std::stoi(tokens[x]));
        }
    }
}

static void load_binary_rgb(
        uint8_t*        dst,
        std::ifstream&  file,
        size_t          width,
        size_t          height,
        int             /*max_value*/
        )
{
//  assert(max_value < 256);    // TODO: 16-bit
//  assert(max_value == 255);   // TODO: scaling

    size_t pitch = width * 3;
    file.read(reinterpret_cast<char*>(dst), pitch * height);
}

//-------------------------------------------------------------------------------------------------
// pnm_image
//

bool pnm_image::load(std::string const& filename)
{
    enum format { P1 = 1, P2, P3, P4, P5, P6 };

    std::ifstream file(filename);

    std::string line;

    //
    // First line determines format:
    // P1: ASCII BW         | P4: binary BW
    // P2: ASCII gray scale | P5: binary gray scale
    // P3: ASCII RGB        | P6: binary RGB
    //
    std::getline(file, line);

    if (line.size() < 2 || line[0] != 'P' || line[1] < '0' || line[1] > '6')
    {
        std::cerr << "Invalid file format: " << line << '\n';
        return false;
    }

    format fmt = static_cast<format>(line[1] - '0');

    // Width and height
    for (;;)
    {
        std::getline(file, line);

        if (line[0] == '#')
        {
            // Skip comments
            continue;
        }
        else
        {
            std::vector<std::string> tokens;
            boost::algorithm::split(
                    tokens,
                    line,
                    boost::algorithm::is_any_of(" \t")
                    );

            if (tokens.size() != 2)
            {
                std::cerr << "Invalid dimensions\n";
                return false;
            }

            width_  = static_cast<size_t>(std::stoi(tokens[0]));
            height_ = static_cast<size_t>(std::stoi(tokens[1]));

            break;
        }
    }

    // Max. value
    int max_value = 255;
    if (fmt != P1 && fmt != P4)
    {
        for (;;)
        {
            std::getline(file, line);

            if (line[0] == '#')
            {
                // Skip comments
                continue;
            }
            else
            {
                max_value = std::stoi(line);
                break;
            }
        }
    }

    switch (fmt)
    {
    default:
        std::cerr << "Unsupported PNM image type: P" << std::to_string(static_cast<int>(fmt)) << '\n';
        width_  = 0;
        height_ = 0;
        format_ = PF_UNSPECIFIED;
        data_.resize(0);
        return false;

    case P3:
        assert(max_value < 256);
        assert(max_value == 255);
        format_ = PF_RGB8;
        data_.resize(width_ * height_ * 3);

        load_ascii_rgb(
                data_.data(),
                file,
                width_,
                height_,
                max_value
                );
        return true;

    case P6:
        assert(max_value < 256);
        assert(max_value == 255);
        format_ = PF_RGB8;
        data_.resize(width_ * height_ * 3);

        load_binary_rgb(
                data_.data(),
                file,
                width_,
                height_,
                max_value
                );
        return true;
    }

    return true;
}

}
<|endoftext|>


<commit_before>/**
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#ifndef __RESOURCES_HPP__
#define __RESOURCES_HPP__

#include <iterator>
#include <string>

#include <mesos/mesos.hpp>

#include "common/foreach.hpp"
#include "common/option.hpp"

// Resources come in three types: scalar, ranges, and sets. These are
// represented using protocol buffers. To make manipulation of
// resources easier within the Mesos core we provide generic
// overloaded opertors (see below) as well as a general Resources
// class that encapsulates a collection of protocol buffer Resource
// objects. The Resources class also provides a few static routines to
// allow parsing resources (e.g., from the command line), as well as
// determining whether or not a Resource object is valid or
// allocatable. In particular, a scalar is allocatable if it's value
// is greater than zero, a ranges is allocatable if there is at least
// one valid range in it, and a set is allocatable if it has at least
// one item. One can get only the allocatable resources by calling the
// allocatable routine on a resources object. Note that many of these
// operations have not been optimized but instead just written for
// correct semantics.

// Note! A resource is described by a tuple (name, type). Doing
// "arithmetic" operations (those defined below) on two resources of
// the same name but different type doesn't make sense, so it's
// semantics are as though the second operand was actually just and
// empty resource (as though you didn't do the operation at all). In
// addition, doing operations on two resources of the same type but
// different names is a no-op.

// Parsing resources can be done via the Resources::parse
// routines. The syntax currently requires that resources are
// separated by semicolons, which means on the command line the option
// needs to be quoted (whitespace is ignored). A scalar is just a
// number, a range is described like "[2-10, 34-56]", and a set like
// "{a, b, c, d}".

namespace mesos {

bool operator == (const Value::Scalar& left, const Value::Scalar& right);
bool operator <= (const Value::Scalar& left, const Value::Scalar& right);
Value::Scalar operator + (const Value::Scalar& left, const Value::Scalar& right);
Value::Scalar operator - (const Value::Scalar& left, const Value::Scalar& right);
Value::Scalar& operator += (Value::Scalar& left, const Value::Scalar& right);
Value::Scalar& operator -= (Value::Scalar& left, const Value::Scalar& right);

bool operator == (const Value::Ranges& left, const Value::Ranges& right);
bool operator <= (const Value::Ranges& left, const Value::Ranges& right);
Value::Ranges operator + (const Value::Ranges& left, const Value::Ranges& right);
Value::Ranges operator - (const Value::Ranges& left, const Value::Ranges& right);
Value::Ranges& operator += (Value::Ranges& left, const Value::Ranges& right);
Value::Ranges& operator -= (Value::Ranges& left, const Value::Ranges& right);

bool operator == (const Value::Set& left, const Value::Set& right);
bool operator <= (const Value::Set& left, const Value::Set& right);
Value::Set operator + (const Value::Set& left, const Value::Set& right);
Value::Set operator - (const Value::Set& left, const Value::Set& right);
Value::Set& operator += (Value::Set& left, const Value::Set& right);
Value::Set& operator -= (Value::Set& left, const Value::Set& right);

bool operator == (const Resource& left, const Resource& right);
bool operator <= (const Resource& left, const Resource& right);
Resource operator + (const Resource& left, const Resource& right);
Resource operator - (const Resource& left, const Resource& right);
Resource& operator += (Resource& left, const Resource& right);
Resource& operator -= (Resource& left, const Resource& right);

std::ostream& operator << (std::ostream& stream, const Resource& resource);

namespace internal {

class Resources
{
public:
  Resources() {}

  Resources(const google::protobuf::RepeatedPtrField<Resource>& _resources)
  {
    resources.MergeFrom(_resources);
  }

  Resources(const Resources& that)
  {
    resources.MergeFrom(that.resources);
  }

  Resources& operator = (const Resources& that)
  {
    if (this != &that) {
      resources.Clear();
      resources.MergeFrom(that.resources);
    }

    return *this;
  }

  // Returns a Resources object with only the allocatable resources.
  Resources allocatable() const
  {
    Resources result;

    foreach (const Resource& resource, resources) {
      if (isAllocatable(resource)) {
        result.resources.Add()->MergeFrom(resource);
      }
    }

    return result;
  }

  size_t size() const
  {
    return resources.size();
  }

  // Using this operator makes it easy to copy a resources object into
  // a protocol buffer field.
  operator const google::protobuf::RepeatedPtrField<Resource>& () const
  {
    return resources;
  }

  bool operator == (const Resources& that) const
  {
    foreach (const Resource& resource, resources) {
      Option<Resource> option = that.get(resource);
      if (option.isNone()) {
        return false;
      } else {
        if (!(resource == option.get())) {
          return false;
        }
      }
    }

    return true;
  }

  bool operator <= (const Resources& that) const
  {
    foreach (const Resource& resource, resources) {
      Option<Resource> option = that.get(resource);
      if (option.isNone()) {
        return false;
      } else {
        if (!(resource <= option.get())) {
          return false;
        }
      }
    }

    return true;
  }

  Resources operator + (const Resources& that) const
  {
    Resources result(*this);

    foreach (const Resource& resource, that.resources) {
      result += resource;
    }

    return result;
  }

  Resources operator - (const Resources& that) const
  {
    Resources result(*this);

    foreach (const Resource& resource, that.resources) {
      result -= resource;
    }

    return result;
  }

  Resources& operator += (const Resources& that)
  {
    foreach (const Resource& resource, that.resources) {
      *this += resource;
    }

    return *this;
  }

  Resources& operator -= (const Resources& that)
  {
    foreach (const Resource& resource, that.resources) {
      *this -= resource;
    }

    return *this;
  }

  Resources operator + (const Resource& that) const
  {
    Resources result;

    bool added = false;

    foreach (const Resource& resource, resources) {
      if (resource.name() == that.name() &&
	resource.type() == that.type()) {
        result.resources.Add()->MergeFrom(resource + that);
        added = true;
      } else {
        result.resources.Add()->MergeFrom(resource);
      }
    }

    if (!added) {
      result.resources.Add()->MergeFrom(that);
    }

    return result;
  }

  Resources operator - (const Resource& that) const
  {
    Resources result;

    foreach (const Resource& resource, resources) {
      if (resource.name() == that.name() &&
	resource.type() == that.type()) {
        result.resources.Add()->MergeFrom(resource - that);
      } else {
        result.resources.Add()->MergeFrom(resource);
      }
    }

    return result;
  }

  Resources& operator += (const Resource& that)
  {
    *this = *this + that;
    return *this;
  }

  Resources& operator -= (const Resource& that)
  {
    *this = *this - that;
    return *this;
  }

  Option<Resource> get(const Resource& r) const
  {
    foreach (const Resource& resource, resources) {
      if (resource.name() == r.name() &&
          resource.type() == r.type()) {
        return resource;
      }
    }

    return Option<Resource>::none();
  }

  template <typename T>
  T get(const std::string& name, const T& t) const;

  typedef google::protobuf::RepeatedPtrField<Resource>::iterator
  iterator;

  typedef google::protobuf::RepeatedPtrField<Resource>::const_iterator
  const_iterator;

  iterator begin() { return resources.begin(); }
  iterator end() { return resources.end(); }

  const_iterator begin() const { return resources.begin(); }
  const_iterator end() const { return resources.end(); }

  static Resource parse(const std::string& name, const std::string& value);
  static Resources parse(const std::string& s);

  static bool isValid(const Resource& resource)
  {
    if (!resource.has_name() ||
        resource.name() == "" ||
        !resource.has_type() ||
        !Value::Type_IsValid(resource.type())) {
      return false;
    }

    if (resource.type() == Value::SCALAR) {
      return resource.has_scalar();
    } else if (resource.type() == Value::RANGES) {
      return resource.has_ranges();
    } else if (resource.type() == Value::SET) {
      return resource.has_ranges();
    } else if (resource.type() == Value::TEXT) {
      // Resources doesn't support text.
      return false;
    }

    return false;
  }

  static bool isAllocatable(const Resource& resource)
  {
    if (isValid(resource)) {
      if (resource.type() == Value::SCALAR) {
        if (resource.scalar().value() <= 0) {
          return false;
        }
      } else if (resource.type() == Value::RANGES) {
        if (resource.ranges().range_size() == 0) {
          return false;
        } else {
          for (int i = 0; i < resource.ranges().range_size(); i++) {
            const Value::Range& range = resource.ranges().range(i);

            // Ensure the range make sense (isn't inverted).
            if (range.begin() > range.end()) {
              return false;
            }

            // Ensure ranges don't overlap (but not necessarily coalesced).
            for (int j = j + 1; j < resource.ranges().range_size(); j++) {
              if (range.begin() <= resource.ranges().range(j).begin() &&
                  resource.ranges().range(j).begin() <= range.end()) {
                return false;
              }
            }
          }
        }
      } else if (resource.type() == Value::SET) {
        if (resource.set().item_size() == 0) {
          return false;
        } else {
          for (int i = 0; i < resource.set().item_size(); i++) {
            const std::string& item = resource.set().item(i);

            // Ensure no duplicates.
            for (int j = i + 1; j < resource.set().item_size(); j++) {
              if (item == resource.set().item(j)) {
                return false;
              }
            }
          }
        }
      }

      return true;
    }

    return false;
  }

private:
  google::protobuf::RepeatedPtrField<Resource> resources;
};

template <>
inline Value::Scalar Resources::get(
    const std::string& name,
    const Value::Scalar& scalar) const
{
  foreach (const Resource& resource, resources) {
    if (resource.name() == name &&
        resource.type() == Value::SCALAR) {
      return resource.scalar();
    }
  }

  return scalar;
}

template <>
inline Value::Ranges Resources::get(
    const std::string& name,
    const Value::Ranges& ranges) const
{
  foreach (const Resource& resource, resources) {
    if (resource.name() == name &&
        resource.type() == Value::RANGES) {
      return resource.ranges();
    }
  }

  return ranges;
}

template <>
inline Value::Set Resources::get(
    const std::string& name,
    const Value::Set& set) const
{
  foreach (const Resource& resource, resources) {
    if (resource.name() == name &&
        resource.type() == Value::SET) {
      return resource.set();
    }
  }

  return set;
}

inline std::ostream& operator << (
    std::ostream& stream,
    const Resources& resources)
{
  mesos::internal::Resources::const_iterator it = resources.begin();

  while (it != resources.end()) {
    stream << *it;
    if (++it != resources.end()) {
      stream << "; ";
    }
  }

  return stream;
}

inline std::ostream& operator << (
    std::ostream& stream,
    const google::protobuf::RepeatedPtrField<Resource>& resources)
{
  return stream << Resources(resources);
}

inline Resources operator + (
    const google::protobuf::RepeatedPtrField<Resource>& left,
    const Resources& right)
{
  return Resources(left) + right;
}

inline Resources operator - (
    const google::protobuf::RepeatedPtrField<Resource>& left,
    const Resources& right)
{
  return Resources(left) - right;
}

inline bool operator == (
    const google::protobuf::RepeatedPtrField<Resource>& left,
    const Resources& right)
{
  return Resources(left) == right;
}

} // namespace internal {
} // namespace mesos {

#endif // __RESOURCES_HPP__
<commit_msg>Minor fix for src/common/resources.hpp to deal with looping error (contributed by Charles Reiss).<commit_after>/**
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#ifndef __RESOURCES_HPP__
#define __RESOURCES_HPP__

#include <iterator>
#include <string>

#include <mesos/mesos.hpp>

#include "common/foreach.hpp"
#include "common/option.hpp"

// Resources come in three types: scalar, ranges, and sets. These are
// represented using protocol buffers. To make manipulation of
// resources easier within the Mesos core we provide generic
// overloaded opertors (see below) as well as a general Resources
// class that encapsulates a collection of protocol buffer Resource
// objects. The Resources class also provides a few static routines to
// allow parsing resources (e.g., from the command line), as well as
// determining whether or not a Resource object is valid or
// allocatable. In particular, a scalar is allocatable if it's value
// is greater than zero, a ranges is allocatable if there is at least
// one valid range in it, and a set is allocatable if it has at least
// one item. One can get only the allocatable resources by calling the
// allocatable routine on a resources object. Note that many of these
// operations have not been optimized but instead just written for
// correct semantics.

// Note! A resource is described by a tuple (name, type). Doing
// "arithmetic" operations (those defined below) on two resources of
// the same name but different type doesn't make sense, so it's
// semantics are as though the second operand was actually just and
// empty resource (as though you didn't do the operation at all). In
// addition, doing operations on two resources of the same type but
// different names is a no-op.

// Parsing resources can be done via the Resources::parse
// routines. The syntax currently requires that resources are
// separated by semicolons, which means on the command line the option
// needs to be quoted (whitespace is ignored). A scalar is just a
// number, a range is described like "[2-10, 34-56]", and a set like
// "{a, b, c, d}".

namespace mesos {

bool operator == (const Value::Scalar& left, const Value::Scalar& right);
bool operator <= (const Value::Scalar& left, const Value::Scalar& right);
Value::Scalar operator + (const Value::Scalar& left, const Value::Scalar& right);
Value::Scalar operator - (const Value::Scalar& left, const Value::Scalar& right);
Value::Scalar& operator += (Value::Scalar& left, const Value::Scalar& right);
Value::Scalar& operator -= (Value::Scalar& left, const Value::Scalar& right);

bool operator == (const Value::Ranges& left, const Value::Ranges& right);
bool operator <= (const Value::Ranges& left, const Value::Ranges& right);
Value::Ranges operator + (const Value::Ranges& left, const Value::Ranges& right);
Value::Ranges operator - (const Value::Ranges& left, const Value::Ranges& right);
Value::Ranges& operator += (Value::Ranges& left, const Value::Ranges& right);
Value::Ranges& operator -= (Value::Ranges& left, const Value::Ranges& right);

bool operator == (const Value::Set& left, const Value::Set& right);
bool operator <= (const Value::Set& left, const Value::Set& right);
Value::Set operator + (const Value::Set& left, const Value::Set& right);
Value::Set operator - (const Value::Set& left, const Value::Set& right);
Value::Set& operator += (Value::Set& left, const Value::Set& right);
Value::Set& operator -= (Value::Set& left, const Value::Set& right);

bool operator == (const Resource& left, const Resource& right);
bool operator <= (const Resource& left, const Resource& right);
Resource operator + (const Resource& left, const Resource& right);
Resource operator - (const Resource& left, const Resource& right);
Resource& operator += (Resource& left, const Resource& right);
Resource& operator -= (Resource& left, const Resource& right);

std::ostream& operator << (std::ostream& stream, const Resource& resource);

namespace internal {

class Resources
{
public:
  Resources() {}

  Resources(const google::protobuf::RepeatedPtrField<Resource>& _resources)
  {
    resources.MergeFrom(_resources);
  }

  Resources(const Resources& that)
  {
    resources.MergeFrom(that.resources);
  }

  Resources& operator = (const Resources& that)
  {
    if (this != &that) {
      resources.Clear();
      resources.MergeFrom(that.resources);
    }

    return *this;
  }

  // Returns a Resources object with only the allocatable resources.
  Resources allocatable() const
  {
    Resources result;

    foreach (const Resource& resource, resources) {
      if (isAllocatable(resource)) {
        result.resources.Add()->MergeFrom(resource);
      }
    }

    return result;
  }

  size_t size() const
  {
    return resources.size();
  }

  // Using this operator makes it easy to copy a resources object into
  // a protocol buffer field.
  operator const google::protobuf::RepeatedPtrField<Resource>& () const
  {
    return resources;
  }

  bool operator == (const Resources& that) const
  {
    foreach (const Resource& resource, resources) {
      Option<Resource> option = that.get(resource);
      if (option.isNone()) {
        return false;
      } else {
        if (!(resource == option.get())) {
          return false;
        }
      }
    }

    return true;
  }

  bool operator <= (const Resources& that) const
  {
    foreach (const Resource& resource, resources) {
      Option<Resource> option = that.get(resource);
      if (option.isNone()) {
        return false;
      } else {
        if (!(resource <= option.get())) {
          return false;
        }
      }
    }

    return true;
  }

  Resources operator + (const Resources& that) const
  {
    Resources result(*this);

    foreach (const Resource& resource, that.resources) {
      result += resource;
    }

    return result;
  }

  Resources operator - (const Resources& that) const
  {
    Resources result(*this);

    foreach (const Resource& resource, that.resources) {
      result -= resource;
    }

    return result;
  }

  Resources& operator += (const Resources& that)
  {
    foreach (const Resource& resource, that.resources) {
      *this += resource;
    }

    return *this;
  }

  Resources& operator -= (const Resources& that)
  {
    foreach (const Resource& resource, that.resources) {
      *this -= resource;
    }

    return *this;
  }

  Resources operator + (const Resource& that) const
  {
    Resources result;

    bool added = false;

    foreach (const Resource& resource, resources) {
      if (resource.name() == that.name() &&
	resource.type() == that.type()) {
        result.resources.Add()->MergeFrom(resource + that);
        added = true;
      } else {
        result.resources.Add()->MergeFrom(resource);
      }
    }

    if (!added) {
      result.resources.Add()->MergeFrom(that);
    }

    return result;
  }

  Resources operator - (const Resource& that) const
  {
    Resources result;

    foreach (const Resource& resource, resources) {
      if (resource.name() == that.name() &&
	resource.type() == that.type()) {
        result.resources.Add()->MergeFrom(resource - that);
      } else {
        result.resources.Add()->MergeFrom(resource);
      }
    }

    return result;
  }

  Resources& operator += (const Resource& that)
  {
    *this = *this + that;
    return *this;
  }

  Resources& operator -= (const Resource& that)
  {
    *this = *this - that;
    return *this;
  }

  Option<Resource> get(const Resource& r) const
  {
    foreach (const Resource& resource, resources) {
      if (resource.name() == r.name() &&
          resource.type() == r.type()) {
        return resource;
      }
    }

    return Option<Resource>::none();
  }

  template <typename T>
  T get(const std::string& name, const T& t) const;

  typedef google::protobuf::RepeatedPtrField<Resource>::iterator
  iterator;

  typedef google::protobuf::RepeatedPtrField<Resource>::const_iterator
  const_iterator;

  iterator begin() { return resources.begin(); }
  iterator end() { return resources.end(); }

  const_iterator begin() const { return resources.begin(); }
  const_iterator end() const { return resources.end(); }

  static Resource parse(const std::string& name, const std::string& value);
  static Resources parse(const std::string& s);

  static bool isValid(const Resource& resource)
  {
    if (!resource.has_name() ||
        resource.name() == "" ||
        !resource.has_type() ||
        !Value::Type_IsValid(resource.type())) {
      return false;
    }

    if (resource.type() == Value::SCALAR) {
      return resource.has_scalar();
    } else if (resource.type() == Value::RANGES) {
      return resource.has_ranges();
    } else if (resource.type() == Value::SET) {
      return resource.has_ranges();
    } else if (resource.type() == Value::TEXT) {
      // Resources doesn't support text.
      return false;
    }

    return false;
  }

  static bool isAllocatable(const Resource& resource)
  {
    if (isValid(resource)) {
      if (resource.type() == Value::SCALAR) {
        if (resource.scalar().value() <= 0) {
          return false;
        }
      } else if (resource.type() == Value::RANGES) {
        if (resource.ranges().range_size() == 0) {
          return false;
        } else {
          for (int i = 0; i < resource.ranges().range_size(); i++) {
            const Value::Range& range = resource.ranges().range(i);

            // Ensure the range make sense (isn't inverted).
            if (range.begin() > range.end()) {
              return false;
            }

            // Ensure ranges don't overlap (but not necessarily coalesced).
            for (int j = i + 1; j < resource.ranges().range_size(); j++) {
              if (range.begin() <= resource.ranges().range(j).begin() &&
                  resource.ranges().range(j).begin() <= range.end()) {
                return false;
              }
            }
          }
        }
      } else if (resource.type() == Value::SET) {
        if (resource.set().item_size() == 0) {
          return false;
        } else {
          for (int i = 0; i < resource.set().item_size(); i++) {
            const std::string& item = resource.set().item(i);

            // Ensure no duplicates.
            for (int j = i + 1; j < resource.set().item_size(); j++) {
              if (item == resource.set().item(j)) {
                return false;
              }
            }
          }
        }
      }

      return true;
    }

    return false;
  }

private:
  google::protobuf::RepeatedPtrField<Resource> resources;
};

template <>
inline Value::Scalar Resources::get(
    const std::string& name,
    const Value::Scalar& scalar) const
{
  foreach (const Resource& resource, resources) {
    if (resource.name() == name &&
        resource.type() == Value::SCALAR) {
      return resource.scalar();
    }
  }

  return scalar;
}

template <>
inline Value::Ranges Resources::get(
    const std::string& name,
    const Value::Ranges& ranges) const
{
  foreach (const Resource& resource, resources) {
    if (resource.name() == name &&
        resource.type() == Value::RANGES) {
      return resource.ranges();
    }
  }

  return ranges;
}

template <>
inline Value::Set Resources::get(
    const std::string& name,
    const Value::Set& set) const
{
  foreach (const Resource& resource, resources) {
    if (resource.name() == name &&
        resource.type() == Value::SET) {
      return resource.set();
    }
  }

  return set;
}

inline std::ostream& operator << (
    std::ostream& stream,
    const Resources& resources)
{
  mesos::internal::Resources::const_iterator it = resources.begin();

  while (it != resources.end()) {
    stream << *it;
    if (++it != resources.end()) {
      stream << "; ";
    }
  }

  return stream;
}

inline std::ostream& operator << (
    std::ostream& stream,
    const google::protobuf::RepeatedPtrField<Resource>& resources)
{
  return stream << Resources(resources);
}

inline Resources operator + (
    const google::protobuf::RepeatedPtrField<Resource>& left,
    const Resources& right)
{
  return Resources(left) + right;
}

inline Resources operator - (
    const google::protobuf::RepeatedPtrField<Resource>& left,
    const Resources& right)
{
  return Resources(left) - right;
}

inline bool operator == (
    const google::protobuf::RepeatedPtrField<Resource>& left,
    const Resources& right)
{
  return Resources(left) == right;
}

} // namespace internal {
} // namespace mesos {

#endif // __RESOURCES_HPP__
<|endoftext|>


<commit_before><commit_msg>removing printf stops output is unparseable error<commit_after><|endoftext|>


<commit_before>//=======================================================================
// Copyright (c) 2013-2014 Baptiste Wicht.
// Distributed under the terms of the MIT License.
// (See accompanying file LICENSE or copy at
//  http://opensource.org/licenses/MIT)
//=======================================================================

#include <iostream>
#include <sstream>
#include <fstream>

#include "versioning.hpp"
#include "budget_exception.hpp"
#include "config.hpp"

namespace {

std::string exec_command(const std::string& command) {
    std::stringstream output;

    char buffer[1024];

    FILE* stream = popen(command.c_str(), "r");

    while (fgets(buffer, 1024, stream) != NULL) {
        output << buffer;
    }

    pclose(stream);

    return output.str();
}

} //end of anonymous namespace

void budget::versioning_module::handle(const std::vector<std::string>& args){
    if(args.size() == 1){
        std::cout << "Missing subcommand" << std::endl;
    } else {
        auto& subcommand = args[1];

        if(subcommand == "save"){
            std::cout << exec_command("git -C " + budget_folder() + " commit -a -m Update" ) << std::endl;
        } else if(subcommand == "sync"){
            std::cout << exec_command("git -C " + budget_folder() + " pull" ) << std::endl;
            std::cout << exec_command("git -C " + budget_folder() + " push" ) << std::endl;
        } else {
            throw budget_exception("Invalid subcommand \"" + subcommand + "\"");
        }
    }
}
<commit_msg>Update functions of versioning<commit_after>//=======================================================================
// Copyright (c) 2013-2014 Baptiste Wicht.
// Distributed under the terms of the MIT License.
// (See accompanying file LICENSE or copy at
//  http://opensource.org/licenses/MIT)
//=======================================================================

#include <iostream>
#include <sstream>
#include <fstream>

#include "versioning.hpp"
#include "budget_exception.hpp"
#include "config.hpp"

namespace {

std::string exec_command(const std::string& command) {
    std::stringstream output;

    char buffer[1024];

    FILE* stream = popen(command.c_str(), "r");

    while (fgets(buffer, 1024, stream) != NULL) {
        output << buffer;
    }

    pclose(stream);

    return output.str();
}

} //end of anonymous namespace

void budget::versioning_module::handle(const std::vector<std::string>& args){
    if(args.size() == 1){
        std::cout << "Missing subcommand" << std::endl;
    } else {
        auto& subcommand = args[1];

        if(subcommand == "save"){
            std::cout << exec_command("git -C " + budget_folder() + " commit -a -m Update" ) << std::endl;
        } else if(subcommand == "sync"){
            std::cout << exec_command("git -C " + budget_folder() + " commit -a -m Update" ) << std::endl;
            std::cout << exec_command("git -C " + budget_folder() + " pull" ) << std::endl;
            std::cout << exec_command("git -C " + budget_folder() + " push" ) << std::endl;
        } else if(subcommand == "pull"){
            std::cout << exec_command("git -C " + budget_folder() + " pull" ) << std::endl;
        } else if(subcommand == "push"){
            std::cout << exec_command("git -C " + budget_folder() + " push" ) << std::endl;
        } else {
            throw budget_exception("Invalid subcommand \"" + subcommand + "\"");
        }
    }
}
<|endoftext|>


<commit_before>
// Qt includes
#include <QApplication>
#include <QDebug>
#include <QFileInfo>
#include <QTreeView>
#include <QSqlQuery>

// ctkDICOMCore includes
#include "ctkDICOM.h"
#include "ctkDICOMModel.h"
#include "ctkModelTester.h"

// STD includes
#include <iostream>

/* Test from build directory:
 ./CTK-build/bin/CTKDICOMCoreCxxTests ctkDICOMModelTest1 test.db ../CTK/Libs/DICOM/Core/Resources/dicom-sample.sql
*/

int ctkDICOMModelTest1( int argc, char * argv [] )
{
  QApplication app(argc, argv);

  if (argc <= 2)
    {
    std::cerr << "Warning, no sql file given. Test stops" << std::endl;
    std::cerr << "Usage: qctkDICOMModelTest1 <scratch.db> <dumpfile.sql>" << std::endl;
    return EXIT_FAILURE;
    }

  ctkDICOM myCTK;
  try
  {
    myCTK.openDatabase( argv[1] );
  }
  catch (std::exception e)
  {
    std::cerr << "Error when opening the data base file: " << argv[1]
              << " error: " << e.what();
    return EXIT_FAILURE;
  }
  if (!myCTK.initializeDatabase(argv[2]))
    {
    std::cerr << "Error when initializing the data base: " << argv[2]
              << " error: " << myCTK.GetLastError().toStdString();
    }
    /*
  QSqlQuery toto("SELECT PatientsName as 'Name tt' FROM Patients ORDER BY \"Name tt\" ASC", myCTK.database());
  qDebug() << "toto: " << myCTK.GetLastError() ;
  qDebug()<< toto.seek(0) << myCTK.GetLastError();
  qDebug() << toto.value(0).toString() << myCTK.GetLastError();

  QSqlQuery titi("SELECT StudyID as UID, StudyDescription as Name, ModalitiesInStudy as Scan, StudyDate as Date, AccessionNumber as Number, ReferringPhysician as Institution, ReferringPhysician as Referrer, PerformingPysiciansName as Performer FROM Studies WHERE PatientsUID='14'", myCTK.database());
  qDebug() << "titi: " << titi.seek(0) << myCTK.GetLastError();
  QSqlQuery tata("SELECT SeriesInstanceUID as UID, BodyPartExamined as Scan, SeriesDate as Date, AcquisitionNumber as Number FROM Series WHERE StudyInstanceUID='1.2.826.0.1.3680043.2.1125.1.73379483469717886505187028001198162'", myCTK.database());
  qDebug() << "tata: " << tata.seek(0) << myCTK.GetLastError();
  QSqlQuery tutu("SELECT Filename as UID, Filename as Name, SeriesInstanceUID as Date FROM Images WHERE SeriesInstanceUID='%1'", myCTK.database());
  qDebug() << "tutu: " << tutu.seek(0) << myCTK.GetLastError();
  */

  ctkModelTester tester;
  tester.setNestedInserts(true);
  tester.setThrowOnError(false);
  ctkDICOMModel model;
  tester.setModel(&model);

  model.setDatabase(myCTK.database());

  model.setDatabase(QSqlDatabase());

  model.setDatabase(myCTK.database());

  QTreeView viewer;
  viewer.setModel(&model);
  viewer.setSortingEnabled(true);

  model.rowCount();
  qDebug() << model.rowCount() << model.columnCount();
  qDebug() << model.index(0,0);
  viewer.show();
  //return app.exec();
  return EXIT_SUCCESS;
}
<commit_msg>Add interaction for ctkDICOMModelTest1<commit_after>
// Qt includes
#include <QApplication>
#include <QDebug>
#include <QFileInfo>
#include <QTreeView>
#include <QSqlQuery>

// ctkDICOMCore includes
#include "ctkDICOM.h"
#include "ctkDICOMModel.h"
#include "ctkModelTester.h"

// STD includes
#include <iostream>

/* Test from build directory:
 ./CTK-build/bin/CTKDICOMCoreCxxTests ctkDICOMModelTest1 test.db ../CTK/Libs/DICOM/Core/Resources/dicom-sample.sql
*/

int ctkDICOMModelTest1( int argc, char * argv [] )
{
  QApplication app(argc, argv);

  if (argc <= 2)
    {
    std::cerr << "Warning, no sql file given. Test stops" << std::endl;
    std::cerr << "Usage: qctkDICOMModelTest1 <scratch.db> <dumpfile.sql>" << std::endl;
    return EXIT_FAILURE;
    }

  ctkDICOM myCTK;
  try
  {
    myCTK.openDatabase( argv[1] );
  }
  catch (std::exception e)
  {
    std::cerr << "Error when opening the data base file: " << argv[1]
              << " error: " << e.what();
    return EXIT_FAILURE;
  }
  if (!myCTK.initializeDatabase(argv[2]))
    {
    std::cerr << "Error when initializing the data base: " << argv[2]
              << " error: " << myCTK.GetLastError().toStdString();
    }
    /*
  QSqlQuery toto("SELECT PatientsName as 'Name tt' FROM Patients ORDER BY \"Name tt\" ASC", myCTK.database());
  qDebug() << "toto: " << myCTK.GetLastError() ;
  qDebug()<< toto.seek(0) << myCTK.GetLastError();
  qDebug() << toto.value(0).toString() << myCTK.GetLastError();

  QSqlQuery titi("SELECT StudyID as UID, StudyDescription as Name, ModalitiesInStudy as Scan, StudyDate as Date, AccessionNumber as Number, ReferringPhysician as Institution, ReferringPhysician as Referrer, PerformingPysiciansName as Performer FROM Studies WHERE PatientsUID='14'", myCTK.database());
  qDebug() << "titi: " << titi.seek(0) << myCTK.GetLastError();
  QSqlQuery tata("SELECT SeriesInstanceUID as UID, BodyPartExamined as Scan, SeriesDate as Date, AcquisitionNumber as Number FROM Series WHERE StudyInstanceUID='1.2.826.0.1.3680043.2.1125.1.73379483469717886505187028001198162'", myCTK.database());
  qDebug() << "tata: " << tata.seek(0) << myCTK.GetLastError();
  QSqlQuery tutu("SELECT Filename as UID, Filename as Name, SeriesInstanceUID as Date FROM Images WHERE SeriesInstanceUID='%1'", myCTK.database());
  qDebug() << "tutu: " << tutu.seek(0) << myCTK.GetLastError();
  */

  ctkModelTester tester;
  tester.setNestedInserts(true);
  tester.setThrowOnError(false);
  ctkDICOMModel model;
  tester.setModel(&model);

  model.setDatabase(myCTK.database());

  model.setDatabase(QSqlDatabase());

  model.setDatabase(myCTK.database());

  QTreeView viewer;
  viewer.setModel(&model);
  viewer.setSortingEnabled(true);

  model.rowCount();
  qDebug() << model.rowCount() << model.columnCount();
  qDebug() << model.index(0,0);
  viewer.show();
  if (argc > 3 && QString(argv[3]) == "-I")
    {
    return app.exec();
    }
  return EXIT_SUCCESS;
}
<|endoftext|>


<commit_before>#include <gst/gst.h>
#include "MediaPipelineImpl.hpp"
#include "MediaObjectImpl.hpp"
#include <jsonrpc/JsonSerializer.hpp>
#include <KurentoException.hpp>
#include <gst/gst.h>
#include <UUIDGenerator.hpp>
#include <MediaSet.hpp>

#define GST_CAT_DEFAULT kurento_media_object_impl
GST_DEBUG_CATEGORY_STATIC (GST_CAT_DEFAULT);
#define GST_DEFAULT_NAME "KurentoMediaObjectImpl"

namespace kurento
{

MediaObjectImpl::MediaObjectImpl (const boost::property_tree::ptree &config)
{
  initialId = createId();
  this->config = config;
}

MediaObjectImpl::MediaObjectImpl (const boost::property_tree::ptree &config,
                                  std::shared_ptr< MediaObject > parent)
{
  this->parent = parent;
  initialId = createId();
  this->config = config;
}

std::shared_ptr<MediaPipeline>
MediaObjectImpl::getMediaPipeline ()
{
  if (parent) {
    return std::dynamic_pointer_cast<MediaObjectImpl> (parent)->getMediaPipeline();
  } else {
    return std::dynamic_pointer_cast<MediaPipeline> (shared_from_this() );
  }
}

std::string
MediaObjectImpl::createId()
{
  std::string uuid = generateUUID();

  if (parent) {
    std::shared_ptr<MediaPipelineImpl> pipeline;

    pipeline = std::dynamic_pointer_cast<MediaPipelineImpl> (getMediaPipeline() );
    return pipeline->getId() + "/" +
           uuid;
  } else {
    return uuid;
  }
}

std::string
MediaObjectImpl::getName()
{
  std::unique_lock<std::recursive_mutex> lck (mutex);

  if (name.empty () ) {
    name = getId ();
  }

  return name;
}

std::string
MediaObjectImpl::getId()
{
  std::unique_lock<std::recursive_mutex> lck (mutex);

  if (id.empty () ) {
    id = this->getType () + "_" + this->initialId;
  }

  return id;
}

void
MediaObjectImpl::setName (const std::string &name)
{
  std::unique_lock<std::recursive_mutex> lck (mutex);

  this->name = name;
}

std::vector<std::shared_ptr<MediaObject>> MediaObjectImpl::getChilds ()
{
  std::vector<std::shared_ptr<MediaObject>> childs;

  for (auto it : MediaSet::getMediaSet ()->getChilds (std::dynamic_pointer_cast
       <MediaObjectImpl> (shared_from_this() ) ) ) {
    childs.push_back (it);
  }

  return childs;
}

MediaObjectImpl::StaticConstructor MediaObjectImpl::staticConstructor;

MediaObjectImpl::StaticConstructor::StaticConstructor()
{
  GST_DEBUG_CATEGORY_INIT (GST_CAT_DEFAULT, GST_DEFAULT_NAME, 0,
                           GST_DEFAULT_NAME);
}

} /* kurento */
<commit_msg>MediaObjectImpl: Set type at the end of the id<commit_after>#include <gst/gst.h>
#include "MediaPipelineImpl.hpp"
#include "MediaObjectImpl.hpp"
#include <jsonrpc/JsonSerializer.hpp>
#include <KurentoException.hpp>
#include <gst/gst.h>
#include <UUIDGenerator.hpp>
#include <MediaSet.hpp>

#define GST_CAT_DEFAULT kurento_media_object_impl
GST_DEBUG_CATEGORY_STATIC (GST_CAT_DEFAULT);
#define GST_DEFAULT_NAME "KurentoMediaObjectImpl"

namespace kurento
{

MediaObjectImpl::MediaObjectImpl (const boost::property_tree::ptree &config)
{
  initialId = createId();
  this->config = config;
}

MediaObjectImpl::MediaObjectImpl (const boost::property_tree::ptree &config,
                                  std::shared_ptr< MediaObject > parent)
{
  this->parent = parent;
  initialId = createId();
  this->config = config;
}

std::shared_ptr<MediaPipeline>
MediaObjectImpl::getMediaPipeline ()
{
  if (parent) {
    return std::dynamic_pointer_cast<MediaObjectImpl> (parent)->getMediaPipeline();
  } else {
    return std::dynamic_pointer_cast<MediaPipeline> (shared_from_this() );
  }
}

std::string
MediaObjectImpl::createId()
{
  std::string uuid = generateUUID();

  if (parent) {
    std::shared_ptr<MediaPipelineImpl> pipeline;

    pipeline = std::dynamic_pointer_cast<MediaPipelineImpl> (getMediaPipeline() );
    return pipeline->getId() + "/" +
           uuid;
  } else {
    return uuid;
  }
}

std::string
MediaObjectImpl::getName()
{
  std::unique_lock<std::recursive_mutex> lck (mutex);

  if (name.empty () ) {
    name = getId ();
  }

  return name;
}

std::string
MediaObjectImpl::getId()
{
  std::unique_lock<std::recursive_mutex> lck (mutex);

  if (id.empty () ) {
    id = this->initialId + "_" + this->getType ();
  }

  return id;
}

void
MediaObjectImpl::setName (const std::string &name)
{
  std::unique_lock<std::recursive_mutex> lck (mutex);

  this->name = name;
}

std::vector<std::shared_ptr<MediaObject>> MediaObjectImpl::getChilds ()
{
  std::vector<std::shared_ptr<MediaObject>> childs;

  for (auto it : MediaSet::getMediaSet ()->getChilds (std::dynamic_pointer_cast
       <MediaObjectImpl> (shared_from_this() ) ) ) {
    childs.push_back (it);
  }

  return childs;
}

MediaObjectImpl::StaticConstructor MediaObjectImpl::staticConstructor;

MediaObjectImpl::StaticConstructor::StaticConstructor()
{
  GST_DEBUG_CATEGORY_INIT (GST_CAT_DEFAULT, GST_DEFAULT_NAME, 0,
                           GST_DEFAULT_NAME);
}

} /* kurento */
<|endoftext|>