<commit_before>#ifndef __Z2H_PARSER__
#define __Z2H_PARSER__ = 1

#include <cmath>
#include <string>
#include <vector>
#include <fstream>
#include <sstream>
#include <iostream>
#include <stddef.h>
#include <sys/stat.h>
#include <functional>

#include "token.hpp"
#include "symbol.hpp"
#include "binder.hpp"

using namespace std::placeholders;

namespace z2h {

    template <typename TAst>
    class Token;

    template <typename TAst>
    class Symbol;

    class ParserException : public std::exception {
        const char          *_file;
        size_t              _line;
        const std::string   _message;
        std::string         _what;
    public:
        ParserException(const char *file, size_t line, const std::string &message)
            : _file(file)
            , _line(line)
            , _message(message) {
            std::ostringstream out;
            out << _file << ":" << _line << " " << _message << std::endl;
            _what = out.str();
        }
        virtual const char * what() const throw() {
            return _what.c_str();
        }
    };

    template <typename TAst, typename TParser>
    struct Parser : public Binder<TAst, TParser> {

        std::string                 source;
        size_t                      position;
        std::vector<Token<TAst> *>  tokens;
        size_t                      index;

        ~Parser() {
            while (!tokens.empty())
                delete tokens.back(), tokens.pop_back();
        }

        Parser()
            : source("")
            , position(0)
            , tokens({})
            , index(0) {
        }

        // Symbols must be defined by the inheriting parser
        virtual std::vector<Symbol<TAst> *> Symbols() = 0;

        Token<TAst> * Scan() {

            auto eof = Symbols()[0];
            Symbol<TAst> *match = nullptr;
            if (position < source.length()) {
                size_t end = position;
                bool skip = false;
                for (auto symbol : Symbols()) {
                    long length = symbol->Scan(symbol, source.substr(position, source.length() - position), position);
                    if (position + abs(length) > end || (match != nullptr && symbol->lbp > match->lbp && position + abs(length) == end)) {
                        match = symbol;
                        end = position + abs(length);
                        skip = length < 0;
                    }
                }
                if (position == end) {
                    throw ParserException(__FILE__, __LINE__, "Parser::Scan: invalid symbol");
                }
                return new Token<TAst>(match, source, position, end - position, skip);
            }
            return new Token<TAst>(eof, source, position, 0, false); //eof
        }

        Token<TAst> * LookAhead(size_t &distance, bool skips = false) {
            Token<TAst> *token = nullptr;
            auto i = index;
            while (distance) {
                if (i < tokens.size()) {
                    token = tokens[i];
                }
                else {
                    token = Scan();
                    position += token->length;
                    tokens.push_back(token);
                }
                if (skips || !token->skip)
                    --distance;
                ++i;
            }
            distance = i - index;
            return token;
        }

        Token<TAst> * Consume(Symbol<TAst> *expected = nullptr, const std::string &message = "") {
            size_t distance = 1;
            auto token = LookAhead(distance);
            index += distance;
            if (nullptr != expected && *expected != *token->symbol)
                throw ParserException(__FILE__, __LINE__, message);
            return token;
        }

        std::string Load(const std::string &filename) {
            struct stat buffer;
            if (stat(filename.c_str(), &buffer) != 0)
                ParserException(__FILE__, __LINE__, filename + " doesn't exist or is unreadable");
            std::ifstream file(filename);
            std::string text((std::istreambuf_iterator<char>(file)), std::istreambuf_iterator<char>());
            source = text;
            return text;
        }

        std::vector<Token<TAst> *> TokenizeFile(const std::string &filename) {
            Load(filename);
            return Tokenize(source);
        }

        std::vector<Token<TAst> *> Tokenize(std::string source) {
            this->index = 0;
            this->source = source;
            auto eof = Symbols()[0];
            auto token = Consume();
            while (*eof != *token->symbol) {
                token = Consume();
            }
            return tokens;
        }

        TAst ParseFile(const std::string &filename) {
            //auto source = Load(filename);
            Load(filename);
            return Parse(source);
        }

        TAst Parse(std::string source) {
            this->index = 0;
            this->source = source;
            return Expression();
        }

        TAst Expression(size_t rbp = 0) {

            auto *curr = Consume();
            if (nullptr == curr->symbol->Nud) {
                std::ostringstream out;
                out << "unexpected: nullptr==Nud curr=" << *curr;
                throw ParserException(__FILE__, __LINE__, out.str());
            }

            TAst left = curr->symbol->Nud(curr);

            size_t distance = 1;
            auto *next = LookAhead(distance);
            while (rbp < next->symbol->lbp) {
                next = Consume();
                left = next->symbol->Led(left, next);
            }

            return left;
        }

        TAst Statement() {
            size_t distance = 1;
            auto *la1 = LookAhead(distance);
            if (la1->symbol->Std) {
                Consume();
                return la1->symbol->Std();
            }
            auto ast = Expression();
            Consume(1, "EndOfStatement expected!");
            return ast;
        }

        size_t Line() {
            return 0;
        }

        size_t Column() {
            return 0;
        }

    };

}

#endif /*__Z2H_PARSER__*/
<commit_msg>renamed Load -> Open ... -sai<commit_after>#ifndef __Z2H_PARSER__
#define __Z2H_PARSER__ = 1

#include <cmath>
#include <string>
#include <vector>
#include <fstream>
#include <sstream>
#include <iostream>
#include <stddef.h>
#include <sys/stat.h>
#include <functional>

#include "token.hpp"
#include "symbol.hpp"
#include "binder.hpp"

using namespace std::placeholders;

namespace z2h {

    template <typename TAst>
    class Token;

    template <typename TAst>
    class Symbol;

    class ParserException : public std::exception {
        const char          *_file;
        size_t              _line;
        const std::string   _message;
        std::string         _what;
    public:
        ParserException(const char *file, size_t line, const std::string &message)
            : _file(file)
            , _line(line)
            , _message(message) {
            std::ostringstream out;
            out << _file << ":" << _line << " " << _message << std::endl;
            _what = out.str();
        }
        virtual const char * what() const throw() {
            return _what.c_str();
        }
    };

    template <typename TAst, typename TParser>
    struct Parser : public Binder<TAst, TParser> {

        std::string                 source;
        size_t                      position;
        std::vector<Token<TAst> *>  tokens;
        size_t                      index;

        ~Parser() {
            while (!tokens.empty())
                delete tokens.back(), tokens.pop_back();
        }

        Parser()
            : source("")
            , position(0)
            , tokens({})
            , index(0) {
        }

        // Symbols must be defined by the inheriting parser
        virtual std::vector<Symbol<TAst> *> Symbols() = 0;

        std::string Open(const std::string &filename) {
            struct stat buffer;
            if (stat(filename.c_str(), &buffer) != 0)
                ParserException(__FILE__, __LINE__, filename + " doesn't exist or is unreadable");
            std::ifstream file(filename);
            std::string text((std::istreambuf_iterator<char>(file)), std::istreambuf_iterator<char>());
            return text;
        }

        Token<TAst> * Scan() {

            auto eof = Symbols()[0];
            Symbol<TAst> *match = nullptr;
            if (position < source.length()) {
                size_t end = position;
                bool skip = false;
                for (auto symbol : Symbols()) {
                    long length = symbol->Scan(symbol, source.substr(position, source.length() - position), position);
                    if (position + abs(length) > end || (match != nullptr && symbol->lbp > match->lbp && position + abs(length) == end)) {
                        match = symbol;
                        end = position + abs(length);
                        skip = length < 0;
                    }
                }
                if (position == end) {
                    throw ParserException(__FILE__, __LINE__, "Parser::Scan: invalid symbol");
                }
                return new Token<TAst>(match, source, position, end - position, skip);
            }
            return new Token<TAst>(eof, source, position, 0, false); //eof
        }

        Token<TAst> * LookAhead(size_t &distance, bool skips = false) {
            Token<TAst> *token = nullptr;
            auto i = index;
            while (distance) {
                if (i < tokens.size()) {
                    token = tokens[i];
                }
                else {
                    token = Scan();
                    position += token->length;
                    tokens.push_back(token);
                }
                if (skips || !token->skip)
                    --distance;
                ++i;
            }
            distance = i - index;
            return token;
        }

        Token<TAst> * Consume(Symbol<TAst> *expected = nullptr, const std::string &message = "") {
            size_t distance = 1;
            auto token = LookAhead(distance);
            index += distance;
            if (nullptr != expected && *expected != *token->symbol)
                throw ParserException(__FILE__, __LINE__, message);
            return token;
        }

        std::vector<Token<TAst> *> TokenizeFile(const std::string &filename) {
            auto source = Open(filename);
            return Tokenize(source);
        }

        std::vector<Token<TAst> *> Tokenize(std::string source) {
            this->index = 0;
            this->source = source;
            auto eof = Symbols()[0];
            auto token = Consume();
            while (*eof != *token->symbol) {
                token = Consume();
            }
            return tokens;
        }

        TAst ParseFile(const std::string &filename) {
            auto source = Open(filename);
            return Parse(source);
        }

        TAst Parse(std::string source) {
            this->index = 0;
            this->source = source;
            return Expression();
        }

        TAst Expression(size_t rbp = 0) {

            auto *curr = Consume();
            if (nullptr == curr->symbol->Nud) {
                std::ostringstream out;
                out << "unexpected: nullptr==Nud curr=" << *curr;
                throw ParserException(__FILE__, __LINE__, out.str());
            }

            TAst left = curr->symbol->Nud(curr);

            size_t distance = 1;
            auto *next = LookAhead(distance);
            while (rbp < next->symbol->lbp) {
                next = Consume();
                left = next->symbol->Led(left, next);
            }

            return left;
        }

        TAst Statement() {
            size_t distance = 1;
            auto *la1 = LookAhead(distance);
            if (la1->symbol->Std) {
                Consume();
                return la1->symbol->Std();
            }
            auto ast = Expression();
            Consume(1, "EndOfStatement expected!");
            return ast;
        }

        size_t Line() {
            return 0;
        }

        size_t Column() {
            return 0;
        }

    };

}

#endif /*__Z2H_PARSER__*/
<|endoftext|>


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

  Program:   Visualization Toolkit
  Module:    vtkElevationFilter.cxx
  Language:  C++
  Date:      $Date$
  Version:   $Revision$

Copyright (c) 1993-2001 Ken Martin, Will Schroeder, Bill Lorensen
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:

 * Redistributions of source code must retain the above copyright notice,
   this list of conditions and the following disclaimer.

 * Redistributions in binary form must reproduce the above copyright notice,
   this list of conditions and the following disclaimer in the documentation
   and/or other materials provided with the distribution.

 * Neither name of Ken Martin, Will Schroeder, or Bill Lorensen nor the names
   of any contributors may be used to endorse or promote products derived
   from this software without specific prior written permission.

 * Modified source versions must be plainly marked as such, and must not be
   misrepresented as being the original software.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS''
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

=========================================================================*/
#include "vtkElevationFilter.h"
#include "vtkMath.h"
#include "vtkObjectFactory.h"
#include "vtkFloatArray.h"

//------------------------------------------------------------------------------
vtkElevationFilter* vtkElevationFilter::New()
{
  // First try to create the object from the vtkObjectFactory
  vtkObject* ret = vtkObjectFactory::CreateInstance("vtkElevationFilter");
  if(ret)
    {
    return (vtkElevationFilter*)ret;
    }
  // If the factory was unable to create the object, then create it here.
  return new vtkElevationFilter;
}

// Construct object with LowPoint=(0,0,0) and HighPoint=(0,0,1). Scalar
// range is (0,1).
vtkElevationFilter::vtkElevationFilter()
{
  this->LowPoint[0] = 0.0;
  this->LowPoint[1] = 0.0;
  this->LowPoint[2] = 0.0;

  this->HighPoint[0] = 0.0;
  this->HighPoint[1] = 0.0;
  this->HighPoint[2] = 1.0;

  this->ScalarRange[0] = 0.0;
  this->ScalarRange[1] = 1.0;
}

//
// Convert position along ray into scalar value.  Example use includes
// coloring terrain by elevation.
//
void vtkElevationFilter::Execute()
{
  vtkIdType numPts, i;
  int j;
  vtkFloatArray *newScalars;
  float l, *x, s, v[3];
  float diffVector[3], diffScalar;
  vtkDataSet *input = this->GetInput();

  // Initialize
  //
  vtkDebugMacro(<<"Generating elevation scalars!");

  // First, copy the input to the output as a starting point
  this->GetOutput()->CopyStructure( input );

  if ( ((numPts=input->GetNumberOfPoints()) < 1) )
    {
    //vtkErrorMacro(<< "No input!");
    return;
    }

  // Allocate
  //
  newScalars = vtkFloatArray::New();
  newScalars->SetNumberOfTuples(numPts);

  // Set up 1D parametric system
  //
  for (i=0; i<3; i++)
    {
    diffVector[i] = this->HighPoint[i] - this->LowPoint[i];
    }
  if ( (l = vtkMath::Dot(diffVector,diffVector)) == 0.0)
    {
    vtkErrorMacro(<< this << ": Bad vector, using (0,0,1)\n");
    diffVector[0] = diffVector[1] = 0.0; diffVector[2] = 1.0;
    l = 1.0;
    }

  // Compute parametric coordinate and map into scalar range
  //
  diffScalar = this->ScalarRange[1] - this->ScalarRange[0];
  for (i=0; i<numPts; i++)
    {
    if ( ! (i % 10000) )
      {
      this->UpdateProgress ((float)i/numPts);
      if (this->GetAbortExecute())
	{
	break;
	}
      }

    x = input->GetPoint(i);
    for (j=0; j<3; j++)
      {
      v[j] = x[j] - this->LowPoint[j];
      }
    s = vtkMath::Dot(v,diffVector) / l;
    s = (s < 0.0 ? 0.0 : s > 1.0 ? 1.0 : s);
    newScalars->SetValue(i,this->ScalarRange[0]+s*diffScalar);
    }

  // Update self
  //
  this->GetOutput()->GetPointData()->CopyScalarsOff();
  this->GetOutput()->GetPointData()->PassData(input->GetPointData());

  this->GetOutput()->GetCellData()->PassData(input->GetCellData());

  newScalars->SetName("Elevation");
  this->GetOutput()->GetPointData()->SetScalars(newScalars);
  newScalars->Delete();
}

void vtkElevationFilter::PrintSelf(ostream& os, vtkIndent indent)
{
  vtkDataSetToDataSetFilter::PrintSelf(os,indent);

  os << indent << "Low Point: (" << this->LowPoint[0] << ", "
                                << this->LowPoint[1] << ", "
                                << this->LowPoint[2] << ")\n";
  os << indent << "High Point: (" << this->HighPoint[0] << ", "
                                << this->HighPoint[1] << ", "
                                << this->HighPoint[2] << ")\n";
  os << indent << "Scalar Range: (" << this->ScalarRange[0] << ", "
                                << this->ScalarRange[1] << ")\n";
}
<commit_msg>ENH:Saner progress reporting<commit_after>/*=========================================================================

  Program:   Visualization Toolkit
  Module:    vtkElevationFilter.cxx
  Language:  C++
  Date:      $Date$
  Version:   $Revision$

Copyright (c) 1993-2001 Ken Martin, Will Schroeder, Bill Lorensen
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:

 * Redistributions of source code must retain the above copyright notice,
   this list of conditions and the following disclaimer.

 * Redistributions in binary form must reproduce the above copyright notice,
   this list of conditions and the following disclaimer in the documentation
   and/or other materials provided with the distribution.

 * Neither name of Ken Martin, Will Schroeder, or Bill Lorensen nor the names
   of any contributors may be used to endorse or promote products derived
   from this software without specific prior written permission.

 * Modified source versions must be plainly marked as such, and must not be
   misrepresented as being the original software.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS''
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

=========================================================================*/
#include "vtkElevationFilter.h"
#include "vtkMath.h"
#include "vtkObjectFactory.h"
#include "vtkFloatArray.h"

//------------------------------------------------------------------------------
vtkElevationFilter* vtkElevationFilter::New()
{
  // First try to create the object from the vtkObjectFactory
  vtkObject* ret = vtkObjectFactory::CreateInstance("vtkElevationFilter");
  if(ret)
    {
    return (vtkElevationFilter*)ret;
    }
  // If the factory was unable to create the object, then create it here.
  return new vtkElevationFilter;
}

// Construct object with LowPoint=(0,0,0) and HighPoint=(0,0,1). Scalar
// range is (0,1).
vtkElevationFilter::vtkElevationFilter()
{
  this->LowPoint[0] = 0.0;
  this->LowPoint[1] = 0.0;
  this->LowPoint[2] = 0.0;

  this->HighPoint[0] = 0.0;
  this->HighPoint[1] = 0.0;
  this->HighPoint[2] = 1.0;

  this->ScalarRange[0] = 0.0;
  this->ScalarRange[1] = 1.0;
}

//
// Convert position along ray into scalar value.  Example use includes
// coloring terrain by elevation.
//
void vtkElevationFilter::Execute()
{
  vtkIdType numPts, i;
  int j;
  vtkFloatArray *newScalars;
  float l, *x, s, v[3];
  float diffVector[3], diffScalar;
  vtkDataSet *input = this->GetInput();
  int abort=0;

  // Initialize
  //
  vtkDebugMacro(<<"Generating elevation scalars!");

  // First, copy the input to the output as a starting point
  this->GetOutput()->CopyStructure( input );

  if ( ((numPts=input->GetNumberOfPoints()) < 1) )
    {
    //vtkErrorMacro(<< "No input!");
    return;
    }

  // Allocate
  //
  newScalars = vtkFloatArray::New();
  newScalars->SetNumberOfTuples(numPts);

  // Set up 1D parametric system
  //
  for (i=0; i<3; i++)
    {
    diffVector[i] = this->HighPoint[i] - this->LowPoint[i];
    }
  if ( (l = vtkMath::Dot(diffVector,diffVector)) == 0.0)
    {
    vtkErrorMacro(<< this << ": Bad vector, using (0,0,1)\n");
    diffVector[0] = diffVector[1] = 0.0; diffVector[2] = 1.0;
    l = 1.0;
    }

  // Compute parametric coordinate and map into scalar range
  //
  int tenth = numPts/10 + 1;
  diffScalar = this->ScalarRange[1] - this->ScalarRange[0];
  for (i=0; i<numPts && !abort; i++)
    {
    if ( ! (i % tenth) )
      {
      this->UpdateProgress ((float)i/numPts);
      abort = this->GetAbortExecute();
      }

    x = input->GetPoint(i);
    for (j=0; j<3; j++)
      {
      v[j] = x[j] - this->LowPoint[j];
      }
    s = vtkMath::Dot(v,diffVector) / l;
    s = (s < 0.0 ? 0.0 : s > 1.0 ? 1.0 : s);
    newScalars->SetValue(i,this->ScalarRange[0]+s*diffScalar);
    }

  // Update self
  //
  this->GetOutput()->GetPointData()->CopyScalarsOff();
  this->GetOutput()->GetPointData()->PassData(input->GetPointData());

  this->GetOutput()->GetCellData()->PassData(input->GetCellData());

  newScalars->SetName("Elevation");
  this->GetOutput()->GetPointData()->SetScalars(newScalars);
  newScalars->Delete();
}

void vtkElevationFilter::PrintSelf(ostream& os, vtkIndent indent)
{
  vtkDataSetToDataSetFilter::PrintSelf(os,indent);

  os << indent << "Low Point: (" << this->LowPoint[0] << ", "
                                << this->LowPoint[1] << ", "
                                << this->LowPoint[2] << ")\n";
  os << indent << "High Point: (" << this->HighPoint[0] << ", "
                                << this->HighPoint[1] << ", "
                                << this->HighPoint[2] << ")\n";
  os << indent << "Scalar Range: (" << this->ScalarRange[0] << ", "
                                << this->ScalarRange[1] << ")\n";
}
<|endoftext|>


<commit_before>#include <iostream>

#include "routing/osrm_routed_wrapper.h"
#include "structures/vroom/input/input.h"
#include "structures/vroom/job.h"
#include "structures/vroom/vehicle.h"
#include "utils/exception.h"

void log_solution(const vroom::Solution& sol, bool geometry) {
  std::cout << "Total cost: " << sol.summary.cost << std::endl;
  std::cout << "Unassigned: " << sol.summary.unassigned << std::endl;

  // Log unassigned jobs if any.
  std::cout << "Unassigned job ids: ";
  for (const auto& j : sol.unassigned) {
    std::cout << j.id << ", ";
  }
  std::cout << std::endl;

  // Describe routes in solution.
  for (const auto& route : sol.routes) {
    std::cout << "Steps for vehicle " << route.vehicle
              << " (cost: " << route.cost;
    std::cout << " - duration: " << route.duration;
    std::cout << " - service: " << route.service;
    if (geometry) {
      std::cout << " - distance: " << route.distance;
    }

    std::cout << ")" << std::endl;

    // Describe all route steps.
    for (const auto& step : route.steps) {
      std::string type;
      switch (step.step_type) {
      case vroom::STEP_TYPE::START:
        type = "Start";
        break;
      case vroom::STEP_TYPE::END:
        type = "End";
        break;
      case vroom::STEP_TYPE::BREAK:
        type = "Break";
        break;
      case vroom::STEP_TYPE::JOB:
        switch (step.job_type) {
        case vroom::JOB_TYPE::SINGLE:
          type = "Job";
          break;
        case vroom::JOB_TYPE::PICKUP:
          type = "Pickup";
          break;
        case vroom::JOB_TYPE::DELIVERY:
          type = "Delivery";
          break;
        }
        break;
      }
      std::cout << type;

      // Add job/pickup/delivery/break ids.
      if (step.step_type != vroom::STEP_TYPE::START and
          step.step_type != vroom::STEP_TYPE::END) {
        std::cout << " " << step.id;
      }

      // Add location if known.
      if (step.location.has_coordinates()) {
        std::cout << " - " << step.location.lon() << ";" << step.location.lat();
      }

      std::cout << " - arrival: " << step.arrival;
      std::cout << " - duration: " << step.duration;
      std::cout << " - service: " << step.service;

      // Add extra step info if geometry is required.
      if (geometry) {
        std::cout << " - distance: " << step.distance;
      }
      std::cout << std::endl;
    }
  }
}

void run_example_with_osrm() {
  bool GEOMETRY = true;
  unsigned amount_dimension = 1;

  // Set OSRM host and port for "car" profile.
  vroom::io::Servers servers;
  servers["car"] = vroom::Server("localhost", "5000");

  vroom::Input problem_instance(amount_dimension, servers, vroom::ROUTER::OSRM);

  problem_instance.set_geometry(GEOMETRY); // Query for route geometry
                                           // after solving.

  // Create one-dimension capacity restrictions to model the situation
  // where one vehicle can handle 4 jobs with deliveries.
  vroom::Amount vehicle_capacity(1);
  vroom::TimeWindow vehicle_tw(28800, 43200); // Working hours.
  // Default "zero" amount data structures with relevant dimension.
  vroom::Amount job_delivery(amount_dimension);
  vroom::Amount job_empty_delivery(amount_dimension);
  job_delivery[0] = 1;

  vroom::Amount job_pickup(amount_dimension);
  vroom::Amount job_empty_pickup(amount_dimension);
  job_pickup[0] = 1;

  vroom::Duration service = 5 * 60; // 5 minutes
  vehicle_capacity[0] = 4;

  // Define vehicle breaks.
  vroom::Break break_1(1, {vroom::TimeWindow(32400, 34200)}, 300);
  vroom::Break break_2(2, {vroom::TimeWindow(34200, 36000)}, 300);

  // Define vehicles (use std::nullopt for no start or no end).
  vroom::Location depot(vroom::Coordinates({{2.35044, 48.71764}}));
  vroom::Vehicle v1(1,                // id
                    depot,            // start
                    depot,            // end
                    "car",            // profile
                    vehicle_capacity, // capacity
                    {1, 14},          // skills
                    vehicle_tw,       // time window
                    {break_1});       // breaks
  problem_instance.add_vehicle(v1);

  vroom::Vehicle v2(2,                // id
                    depot,            // start
                    depot,            // end
                    "car",            // profile
                    vehicle_capacity, // capacity
                    {2, 14},          // skills
                    vehicle_tw,       // time window
                    {break_2});       // breaks

  problem_instance.add_vehicle(v2);

  // Job to be done between 9 and 10 AM.
  std::vector<vroom::TimeWindow> job_1_tws({{32400, 36000}});

  // Set jobs id, location, service time, amount, required skills,
  // priority and time windows. Constraints that are not required can
  // be omitted.
  std::vector<vroom::Job> jobs;
  jobs.push_back(vroom::Job(1,
                            vroom::Coordinates({{1.98935, 48.701}}),
                            service,
                            job_delivery,
                            job_empty_pickup,
                            {1}, // skills
                            0,   // default priority
                            job_1_tws));
  jobs.push_back(vroom::Job(2,
                            vroom::Coordinates({{2.03655, 48.61128}}),
                            service,
                            job_empty_delivery,
                            job_pickup,
                            {1}));
  jobs.push_back(vroom::Job(5,
                            vroom::Coordinates({{2.28325, 48.5958}}),
                            service,
                            job_delivery,
                            job_empty_pickup,
                            {14}));
  jobs.push_back(vroom::Job(6,
                            vroom::Coordinates({{2.89357, 48.90736}}),
                            service,
                            job_delivery,
                            job_empty_pickup,
                            {14}));

  for (const auto& j : jobs) {
    problem_instance.add_job(j);
  }

  // Define a shipment.
  vroom::Skills pd_skills({2});
  vroom::Amount pd_amount(amount_dimension);
  pd_amount[0] = 1;

  vroom::Job pickup(4,
                    vroom::JOB_TYPE::PICKUP,
                    vroom::Coordinates({{2.41808, 49.22619}}),
                    service,
                    pd_amount,
                    pd_skills);

  vroom::Job delivery(3,
                      vroom::JOB_TYPE::DELIVERY,
                      vroom::Coordinates({{2.39719, 49.07611}}),
                      service,
                      pd_amount,
                      pd_skills);
  problem_instance.add_shipment(pickup, delivery);

  // Skills definitions set the following constraints:
  // - jobs 1 and 2 can only be served by vehicle 1
  // - jobs 3 and 4 can only be served by vehicle 2
  // - jobs 5 and 6 can be served by either one of the vehicles

  // Solve!
  auto sol = problem_instance.solve(5,  // Exploration level.
                                    4); // Use 4 threads.

  log_solution(sol, GEOMETRY);
}

void run_example_with_custom_matrix() {
  bool GEOMETRY = false;
  unsigned amount_dimension = 0; // No capacity constraint.

  vroom::Input problem_instance(amount_dimension);

  // Define custom matrix and bypass OSRM call.
  vroom::Matrix<vroom::Cost> matrix_input({{0, 2104, 197, 1299},
                                           {2103, 0, 2255, 3152},
                                           {197, 2256, 0, 1102},
                                           {1299, 3153, 1102, 0}});
  problem_instance.set_matrix(std::move(matrix_input));

  // Define vehicles (use std::nullopt for no start or no end).
  vroom::Location v_start(0); // index in the provided matrix.
  vroom::Location v_end(3);   // index in the provided matrix.

  vroom::Vehicle v(0,       // id
                   v_start, // start
                   v_end);  // end
  problem_instance.add_vehicle(v);

  // Define jobs with id and index of location in the matrix
  // (coordinates are optional). Constraints that are not required can
  // be omitted.
  std::vector<vroom::Job> jobs;
  jobs.push_back(vroom::Job(1414, 1));
  jobs.push_back(vroom::Job(1515, 2));

  for (const auto& j : jobs) {
    problem_instance.add_job(j);
  }

  // Solve!
  auto sol = problem_instance.solve(5,  // Exploration level.
                                    4); // Use 4 threads.

  log_solution(sol, GEOMETRY);
}

int main() {
  try {
    run_example_with_osrm();
    // run_example_with_custom_matrix();
  } catch (const vroom::Exception& e) {
    std::cerr << "[Error] " << e.message << std::endl;
  }
  return 0;
}
<commit_msg>Fix set_matrix call in libvroom example.<commit_after>#include <iostream>

#include "routing/osrm_routed_wrapper.h"
#include "structures/vroom/input/input.h"
#include "structures/vroom/job.h"
#include "structures/vroom/vehicle.h"
#include "utils/exception.h"

void log_solution(const vroom::Solution& sol, bool geometry) {
  std::cout << "Total cost: " << sol.summary.cost << std::endl;
  std::cout << "Unassigned: " << sol.summary.unassigned << std::endl;

  // Log unassigned jobs if any.
  std::cout << "Unassigned job ids: ";
  for (const auto& j : sol.unassigned) {
    std::cout << j.id << ", ";
  }
  std::cout << std::endl;

  // Describe routes in solution.
  for (const auto& route : sol.routes) {
    std::cout << "Steps for vehicle " << route.vehicle
              << " (cost: " << route.cost;
    std::cout << " - duration: " << route.duration;
    std::cout << " - service: " << route.service;
    if (geometry) {
      std::cout << " - distance: " << route.distance;
    }

    std::cout << ")" << std::endl;

    // Describe all route steps.
    for (const auto& step : route.steps) {
      std::string type;
      switch (step.step_type) {
      case vroom::STEP_TYPE::START:
        type = "Start";
        break;
      case vroom::STEP_TYPE::END:
        type = "End";
        break;
      case vroom::STEP_TYPE::BREAK:
        type = "Break";
        break;
      case vroom::STEP_TYPE::JOB:
        switch (step.job_type) {
        case vroom::JOB_TYPE::SINGLE:
          type = "Job";
          break;
        case vroom::JOB_TYPE::PICKUP:
          type = "Pickup";
          break;
        case vroom::JOB_TYPE::DELIVERY:
          type = "Delivery";
          break;
        }
        break;
      }
      std::cout << type;

      // Add job/pickup/delivery/break ids.
      if (step.step_type != vroom::STEP_TYPE::START and
          step.step_type != vroom::STEP_TYPE::END) {
        std::cout << " " << step.id;
      }

      // Add location if known.
      if (step.location.has_coordinates()) {
        std::cout << " - " << step.location.lon() << ";" << step.location.lat();
      }

      std::cout << " - arrival: " << step.arrival;
      std::cout << " - duration: " << step.duration;
      std::cout << " - service: " << step.service;

      // Add extra step info if geometry is required.
      if (geometry) {
        std::cout << " - distance: " << step.distance;
      }
      std::cout << std::endl;
    }
  }
}

void run_example_with_osrm() {
  bool GEOMETRY = true;
  unsigned amount_dimension = 1;

  // Set OSRM host and port for "car" profile.
  vroom::io::Servers servers;
  servers["car"] = vroom::Server("localhost", "5000");

  vroom::Input problem_instance(amount_dimension, servers, vroom::ROUTER::OSRM);

  problem_instance.set_geometry(GEOMETRY); // Query for route geometry
                                           // after solving.

  // Create one-dimension capacity restrictions to model the situation
  // where one vehicle can handle 4 jobs with deliveries.
  vroom::Amount vehicle_capacity(1);
  vroom::TimeWindow vehicle_tw(28800, 43200); // Working hours.
  // Default "zero" amount data structures with relevant dimension.
  vroom::Amount job_delivery(amount_dimension);
  vroom::Amount job_empty_delivery(amount_dimension);
  job_delivery[0] = 1;

  vroom::Amount job_pickup(amount_dimension);
  vroom::Amount job_empty_pickup(amount_dimension);
  job_pickup[0] = 1;

  vroom::Duration service = 5 * 60; // 5 minutes
  vehicle_capacity[0] = 4;

  // Define vehicle breaks.
  vroom::Break break_1(1, {vroom::TimeWindow(32400, 34200)}, 300);
  vroom::Break break_2(2, {vroom::TimeWindow(34200, 36000)}, 300);

  // Define vehicles (use std::nullopt for no start or no end).
  vroom::Location depot(vroom::Coordinates({{2.35044, 48.71764}}));
  vroom::Vehicle v1(1,                // id
                    depot,            // start
                    depot,            // end
                    "car",            // profile
                    vehicle_capacity, // capacity
                    {1, 14},          // skills
                    vehicle_tw,       // time window
                    {break_1});       // breaks
  problem_instance.add_vehicle(v1);

  vroom::Vehicle v2(2,                // id
                    depot,            // start
                    depot,            // end
                    "car",            // profile
                    vehicle_capacity, // capacity
                    {2, 14},          // skills
                    vehicle_tw,       // time window
                    {break_2});       // breaks

  problem_instance.add_vehicle(v2);

  // Job to be done between 9 and 10 AM.
  std::vector<vroom::TimeWindow> job_1_tws({{32400, 36000}});

  // Set jobs id, location, service time, amount, required skills,
  // priority and time windows. Constraints that are not required can
  // be omitted.
  std::vector<vroom::Job> jobs;
  jobs.push_back(vroom::Job(1,
                            vroom::Coordinates({{1.98935, 48.701}}),
                            service,
                            job_delivery,
                            job_empty_pickup,
                            {1}, // skills
                            0,   // default priority
                            job_1_tws));
  jobs.push_back(vroom::Job(2,
                            vroom::Coordinates({{2.03655, 48.61128}}),
                            service,
                            job_empty_delivery,
                            job_pickup,
                            {1}));
  jobs.push_back(vroom::Job(5,
                            vroom::Coordinates({{2.28325, 48.5958}}),
                            service,
                            job_delivery,
                            job_empty_pickup,
                            {14}));
  jobs.push_back(vroom::Job(6,
                            vroom::Coordinates({{2.89357, 48.90736}}),
                            service,
                            job_delivery,
                            job_empty_pickup,
                            {14}));

  for (const auto& j : jobs) {
    problem_instance.add_job(j);
  }

  // Define a shipment.
  vroom::Skills pd_skills({2});
  vroom::Amount pd_amount(amount_dimension);
  pd_amount[0] = 1;

  vroom::Job pickup(4,
                    vroom::JOB_TYPE::PICKUP,
                    vroom::Coordinates({{2.41808, 49.22619}}),
                    service,
                    pd_amount,
                    pd_skills);

  vroom::Job delivery(3,
                      vroom::JOB_TYPE::DELIVERY,
                      vroom::Coordinates({{2.39719, 49.07611}}),
                      service,
                      pd_amount,
                      pd_skills);
  problem_instance.add_shipment(pickup, delivery);

  // Skills definitions set the following constraints:
  // - jobs 1 and 2 can only be served by vehicle 1
  // - jobs 3 and 4 can only be served by vehicle 2
  // - jobs 5 and 6 can be served by either one of the vehicles

  // Solve!
  auto sol = problem_instance.solve(5,  // Exploration level.
                                    4); // Use 4 threads.

  log_solution(sol, GEOMETRY);
}

void run_example_with_custom_matrix() {
  bool GEOMETRY = false;
  unsigned amount_dimension = 0; // No capacity constraint.

  vroom::Input problem_instance(amount_dimension);

  // Define custom matrix and bypass OSRM call.
  vroom::Matrix<vroom::Cost> matrix_input({{0, 2104, 197, 1299},
                                           {2103, 0, 2255, 3152},
                                           {197, 2256, 0, 1102},
                                           {1299, 3153, 1102, 0}});
  problem_instance.set_matrix("car", std::move(matrix_input));

  // Define vehicles (use std::nullopt for no start or no end).
  vroom::Location v_start(0); // index in the provided matrix.
  vroom::Location v_end(3);   // index in the provided matrix.

  vroom::Vehicle v(0,       // id
                   v_start, // start
                   v_end);  // end
  problem_instance.add_vehicle(v);

  // Define jobs with id and index of location in the matrix
  // (coordinates are optional). Constraints that are not required can
  // be omitted.
  std::vector<vroom::Job> jobs;
  jobs.push_back(vroom::Job(1414, 1));
  jobs.push_back(vroom::Job(1515, 2));

  for (const auto& j : jobs) {
    problem_instance.add_job(j);
  }

  // Solve!
  auto sol = problem_instance.solve(5,  // Exploration level.
                                    4); // Use 4 threads.

  log_solution(sol, GEOMETRY);
}

int main() {
  try {
    run_example_with_osrm();
    // run_example_with_custom_matrix();
  } catch (const vroom::Exception& e) {
    std::cerr << "[Error] " << e.message << std::endl;
  }
  return 0;
}
<|endoftext|>


<commit_before>/**
 * This file is part of Slideshow.
 * Copyright (C) 2008 David Sveningsson <ext@sidvind.com>
 *
 * Slideshow is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as
 * published by the Free Software Foundation, either version 3 of the
 * License, or (at your option) any later version.
 *
 * Slideshow is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with Slideshow.  If not, see <http://www.gnu.org/licenses/>.
 */

#include "config.h"
#include "Exceptions.h"
#include "Graphics.h"
#include "Kernel.h"
#include "OS.h"
#include "Log.h"
#include "Transition.h"
#include <GL/gl.h>
#include <cstdlib>

#include <portable/string.h>
#include <FreeImage.h>

static void FreeImageErrorHandler(FREE_IMAGE_FORMAT fif, const char *message) {
	const char* format = fif != FIF_UNKNOWN ? FreeImage_GetFormatFromFIF(fif) : "Unknown";
	Log::message(Log::Verbose, "FreeImage: An error occured while loading an image\n");
    Log::message(Log::Debug, "FreeImage: Format: %s Message: %s\n", format, message);
}

static FIBITMAP* GenericLoader(const char* lpszPathName, int flag = 0) {
    FREE_IMAGE_FORMAT fif = FreeImage_GetFileType(lpszPathName, 0);

    if ( fif == FIF_UNKNOWN ) {
    	fif = FreeImage_GetFIFFromFilename(lpszPathName);
	}

    if ( fif == FIF_UNKNOWN ) {
    	throw GraphicsException("FreeImage: unknown format, or FreeImage does not handle it.");
    }

    if ( !FreeImage_FIFSupportsReading(fif) ){
    	throw GraphicsException("FreeImage: cannot read this format.");
    }

    return FreeImage_Load(fif, lpszPathName, flag);
}
Graphics::Graphics(int width, int height, bool fullscreen):
	_transition(NULL),
	texture_0(0),
	texture_1(0){

	OS::init_view(width, height, fullscreen);
	Log::message(Log::Verbose, "Graphics: Using resoultion %dx%d\n", width, height);

	freeimage_init();
	gl_setup();
	gl_set_matrices();
	gl_init_textures();
}

Graphics::~Graphics(){
	gl_cleanup_textures();
	freeimage_cleanup();

	if ( _transition && _transition->cleanup ){
		_transition->cleanup();
	}

	free(_transition);

	OS::cleanup();
}

void Graphics::freeimage_init(){
	FreeImage_Initialise();
	FreeImage_SetOutputMessage(FreeImageErrorHandler);
}

void Graphics::freeimage_cleanup(){
	FreeImage_DeInitialise();
}

void Graphics::gl_setup(){
	glShadeModel( GL_FLAT );
	glHint( GL_PERSPECTIVE_CORRECTION_HINT, GL_FASTEST );
	glClearColor(0, 0, 0, 1);
	glColor4f(1, 1, 1, 1);

	glDisable( GL_DEPTH_TEST );
	glDisable( GL_LIGHTING );
	glDisable(GL_ALPHA_TEST);

	glEnable( GL_TEXTURE_2D );
	glEnable(GL_BLEND);
	glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

	glClear( GL_COLOR_BUFFER_BIT );
}

void Graphics::gl_set_matrices(){
	glMatrixMode(GL_PROJECTION);
	glLoadIdentity();

	glOrtho(0, 1, 0, 1, -1.0, 1.0);
	glScalef(1, -1, 1);
	glTranslated(0, -1, 0);

	glEnable(GL_CULL_FACE);

	glMatrixMode(GL_MODELVIEW);
	glLoadIdentity();
}

void Graphics::gl_init_textures(){
	glGenTextures(1, &texture_0);
	glGenTextures(1, &texture_1);
}

void Graphics::gl_cleanup_textures(){
	glDeleteTextures(1, &texture_0);
	glDeleteTextures(1, &texture_1);
}

void Graphics::render(float state){
	transition_context_t context;

	context.texture[0] = texture_0;
	context.texture[1] = texture_1;
	context.state = state;

	_transition->render(&context);

	OS::swap_gl_buffers();
}

void Graphics::load_image(const char* name){
	swap_textures();

	BYTE black[] = {
		0, 0, 0
	};
	BYTE *pixels = black;
	FIBITMAP* dib_resized = NULL;

	int width = 1;
	int height = 1;

	glBindTexture(GL_TEXTURE_2D, texture_0);

	if ( name ){
		char* path = Kernel::real_path(name);

		FIBITMAP* dib = GenericLoader(path);

		if( !dib ){
			throw GraphicsException("Failed to load image '%s'", path);
		}

		free(path);

		FreeImage_FlipVertical(dib);

		FIBITMAP* dib32 = FreeImage_ConvertTo24Bits(dib);

		width = 1024;
		height = 1024;

		dib_resized = FreeImage_Rescale(dib32, width, height, FILTER_BILINEAR);

		pixels = (BYTE*)FreeImage_GetBits(dib_resized);

		FreeImage_Unload(dib);
		FreeImage_Unload(dib32);
	}

    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);

    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_BGR_EXT, GL_UNSIGNED_BYTE, pixels);

    if ( name ){
    	FreeImage_Unload(dib_resized);
    }
}

void Graphics::swap_textures(){
	unsigned int tmp = texture_0;
	texture_0 = texture_1;
	texture_1 = tmp;
}

void Graphics::set_transition(transition_module_t* module){
	if ( _transition && _transition->cleanup ){
		_transition->cleanup();
	}

	_transition = module;

	if ( _transition && _transition->init ){
		_transition->init();
	}
}
<commit_msg>Memoryleak if an image could not be loaded<commit_after>/**
 * This file is part of Slideshow.
 * Copyright (C) 2008 David Sveningsson <ext@sidvind.com>
 *
 * Slideshow is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as
 * published by the Free Software Foundation, either version 3 of the
 * License, or (at your option) any later version.
 *
 * Slideshow is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with Slideshow.  If not, see <http://www.gnu.org/licenses/>.
 */

#include "config.h"
#include "Exceptions.h"
#include "Graphics.h"
#include "Kernel.h"
#include "OS.h"
#include "Log.h"
#include "Transition.h"
#include <GL/gl.h>
#include <cstdlib>

#include <portable/string.h>
#include <FreeImage.h>

static void FreeImageErrorHandler(FREE_IMAGE_FORMAT fif, const char *message) {
	const char* format = fif != FIF_UNKNOWN ? FreeImage_GetFormatFromFIF(fif) : "Unknown";
	Log::message(Log::Verbose, "FreeImage: An error occured while loading an image\n");
    Log::message(Log::Debug, "FreeImage: Format: %s Message: %s\n", format, message);
}

static FIBITMAP* GenericLoader(const char* lpszPathName, int flag = 0) {
    FREE_IMAGE_FORMAT fif = FreeImage_GetFileType(lpszPathName, 0);

    if ( fif == FIF_UNKNOWN ) {
    	fif = FreeImage_GetFIFFromFilename(lpszPathName);
	}

    if ( fif == FIF_UNKNOWN ) {
    	throw GraphicsException("FreeImage: unknown format, or FreeImage does not handle it.");
    }

    if ( !FreeImage_FIFSupportsReading(fif) ){
    	throw GraphicsException("FreeImage: cannot read this format.");
    }

    return FreeImage_Load(fif, lpszPathName, flag);
}
Graphics::Graphics(int width, int height, bool fullscreen):
	_transition(NULL),
	texture_0(0),
	texture_1(0){

	OS::init_view(width, height, fullscreen);
	Log::message(Log::Verbose, "Graphics: Using resoultion %dx%d\n", width, height);

	freeimage_init();
	gl_setup();
	gl_set_matrices();
	gl_init_textures();
}

Graphics::~Graphics(){
	gl_cleanup_textures();
	freeimage_cleanup();

	if ( _transition && _transition->cleanup ){
		_transition->cleanup();
	}

	free(_transition);

	OS::cleanup();
}

void Graphics::freeimage_init(){
	FreeImage_Initialise();
	FreeImage_SetOutputMessage(FreeImageErrorHandler);
}

void Graphics::freeimage_cleanup(){
	FreeImage_DeInitialise();
}

void Graphics::gl_setup(){
	glShadeModel( GL_FLAT );
	glHint( GL_PERSPECTIVE_CORRECTION_HINT, GL_FASTEST );
	glClearColor(0, 0, 0, 1);
	glColor4f(1, 1, 1, 1);

	glDisable( GL_DEPTH_TEST );
	glDisable( GL_LIGHTING );
	glDisable(GL_ALPHA_TEST);

	glEnable( GL_TEXTURE_2D );
	glEnable(GL_BLEND);
	glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

	glClear( GL_COLOR_BUFFER_BIT );
}

void Graphics::gl_set_matrices(){
	glMatrixMode(GL_PROJECTION);
	glLoadIdentity();

	glOrtho(0, 1, 0, 1, -1.0, 1.0);
	glScalef(1, -1, 1);
	glTranslated(0, -1, 0);

	glEnable(GL_CULL_FACE);

	glMatrixMode(GL_MODELVIEW);
	glLoadIdentity();
}

void Graphics::gl_init_textures(){
	glGenTextures(1, &texture_0);
	glGenTextures(1, &texture_1);
}

void Graphics::gl_cleanup_textures(){
	glDeleteTextures(1, &texture_0);
	glDeleteTextures(1, &texture_1);
}

void Graphics::render(float state){
	transition_context_t context;

	context.texture[0] = texture_0;
	context.texture[1] = texture_1;
	context.state = state;

	_transition->render(&context);

	OS::swap_gl_buffers();
}

void Graphics::load_image(const char* name){
	swap_textures();

	BYTE black[] = {
		0, 0, 0
	};
	BYTE *pixels = black;
	FIBITMAP* dib_resized = NULL;

	int width = 1;
	int height = 1;

	glBindTexture(GL_TEXTURE_2D, texture_0);

	if ( name ){
		char* path = Kernel::real_path(name);

		FIBITMAP* dib = GenericLoader(path);

		if( !dib ){
			free(path);
			throw GraphicsException("Failed to load image '%s'", path);
		}

		free(path);

		FreeImage_FlipVertical(dib);

		FIBITMAP* dib32 = FreeImage_ConvertTo24Bits(dib);

		width = 1024;
		height = 1024;

		dib_resized = FreeImage_Rescale(dib32, width, height, FILTER_BILINEAR);

		pixels = (BYTE*)FreeImage_GetBits(dib_resized);

		FreeImage_Unload(dib);
		FreeImage_Unload(dib32);
	}

    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);

    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_BGR_EXT, GL_UNSIGNED_BYTE, pixels);

    if ( name ){
    	FreeImage_Unload(dib_resized);
    }
}

void Graphics::swap_textures(){
	unsigned int tmp = texture_0;
	texture_0 = texture_1;
	texture_1 = tmp;
}

void Graphics::set_transition(transition_module_t* module){
	if ( _transition && _transition->cleanup ){
		_transition->cleanup();
	}

	_transition = module;

	if ( _transition && _transition->init ){
		_transition->init();
	}
}
<|endoftext|>


<commit_before>//===- unittests/AST/PostOrderASTVisitor.cpp - Declaration printer tests --===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file contains tests for the post-order traversing functionality
// of RecursiveASTVisitor.
//
//===----------------------------------------------------------------------===//

#include "clang/AST/RecursiveASTVisitor.h"
#include "clang/Tooling/Tooling.h"
#include "gtest/gtest.h"

using namespace clang;

namespace {

  class RecordingVisitor
    : public RecursiveASTVisitor<RecordingVisitor> {

    bool VisitPostOrder;
  public:
    explicit RecordingVisitor(bool VisitPostOrder)
      : VisitPostOrder(VisitPostOrder) {
    }

    // List of visited nodes during traversal.
    std::vector<std::string> VisitedNodes;

    bool shouldTraversePostOrder() const { return VisitPostOrder; }

    bool VisitUnaryOperator(UnaryOperator *Op) {
      VisitedNodes.push_back(Op->getOpcodeStr(Op->getOpcode()));
      return true;
    }

    bool VisitBinaryOperator(BinaryOperator *Op) {
      VisitedNodes.push_back(Op->getOpcodeStr());
      return true;
    }

    bool VisitIntegerLiteral(IntegerLiteral *Lit) {
      VisitedNodes.push_back(Lit->getValue().toString(10, false));
      return true;
    }

    bool VisitVarDecl(VarDecl* D) {
      VisitedNodes.push_back(D->getNameAsString());
      return true;
    }

    bool VisitCXXMethodDecl(CXXMethodDecl *D) {
      VisitedNodes.push_back(D->getQualifiedNameAsString());
      return true;
    }

    bool VisitReturnStmt(ReturnStmt *S) {
      VisitedNodes.push_back("return");
      return true;
    }

    bool VisitCXXRecordDecl(CXXRecordDecl *Declaration) {
      VisitedNodes.push_back(Declaration->getQualifiedNameAsString());
      return true;
    }

    bool VisitTemplateTypeParmType(TemplateTypeParmType *T) {
      VisitedNodes.push_back(T->getDecl()->getQualifiedNameAsString());
      return true;
    }
  };

}

TEST(RecursiveASTVisitor, PostOrderTraversal) {
  auto ASTUnit = tooling::buildASTFromCode(
    "class A {"
    "  class B {"
    "    int foo() { while(4) { int i = 9; int j = -i; } return (1 + 3) + 2; }"
    "  };"
    "};"
  );
  auto TU = ASTUnit->getASTContext().getTranslationUnitDecl();
  // We traverse the translation unit and store all
  // visited nodes.
  RecordingVisitor Visitor(true);
  Visitor.TraverseTranslationUnitDecl(TU);

  std::vector<std::string> expected = {
    "4", "9", "i", "-", "j", "1", "3", "+", "2", "+", "return", "A::B::foo", "A::B", "A"
  };
  // Compare the list of actually visited nodes
  // with the expected list of visited nodes.
  ASSERT_EQ(expected.size(), Visitor.VisitedNodes.size());
  for (std::size_t I = 0; I < expected.size(); I++) {
    ASSERT_EQ(expected[I], Visitor.VisitedNodes[I]);
  }
}

TEST(RecursiveASTVisitor, NoPostOrderTraversal) {
  auto ASTUnit = tooling::buildASTFromCode(
    "class A {"
    "  class B {"
    "    int foo() { return 1 + 2; }"
    "  };"
    "};"
  );
  auto TU = ASTUnit->getASTContext().getTranslationUnitDecl();
  // We traverse the translation unit and store all
  // visited nodes.
  RecordingVisitor Visitor(false);
  Visitor.TraverseTranslationUnitDecl(TU);

  std::vector<std::string> expected = {
    "A", "A::B", "A::B::foo", "return", "+", "1", "2"
  };
  // Compare the list of actually visited nodes
  // with the expected list of visited nodes.
  ASSERT_EQ(expected.size(), Visitor.VisitedNodes.size());
  for (std::size_t I = 0; I < expected.size(); I++) {
    ASSERT_EQ(expected[I], Visitor.VisitedNodes[I]);
  }
}
<commit_msg>[RecursiveASTVisitor] Improve post-order traversal unit test<commit_after>//===- unittests/AST/PostOrderASTVisitor.cpp - Declaration printer tests --===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file contains tests for the post-order traversing functionality
// of RecursiveASTVisitor.
//
//===----------------------------------------------------------------------===//

#include "clang/AST/RecursiveASTVisitor.h"
#include "clang/Tooling/Tooling.h"
#include "gtest/gtest.h"

using namespace clang;

namespace {

  class RecordingVisitor
    : public RecursiveASTVisitor<RecordingVisitor> {

    bool VisitPostOrder;
  public:
    explicit RecordingVisitor(bool VisitPostOrder)
      : VisitPostOrder(VisitPostOrder) {
    }

    // List of visited nodes during traversal.
    std::vector<std::string> VisitedNodes;

    bool shouldTraversePostOrder() const { return VisitPostOrder; }

    bool VisitUnaryOperator(UnaryOperator *Op) {
      VisitedNodes.push_back(Op->getOpcodeStr(Op->getOpcode()));
      return true;
    }

    bool VisitBinaryOperator(BinaryOperator *Op) {
      VisitedNodes.push_back(Op->getOpcodeStr());
      return true;
    }

    bool VisitIntegerLiteral(IntegerLiteral *Lit) {
      VisitedNodes.push_back(Lit->getValue().toString(10, false));
      return true;
    }

    bool VisitVarDecl(VarDecl* D) {
      VisitedNodes.push_back(D->getNameAsString());
      return true;
    }

    bool VisitCXXMethodDecl(CXXMethodDecl *D) {
      VisitedNodes.push_back(D->getQualifiedNameAsString());
      return true;
    }

    bool VisitReturnStmt(ReturnStmt *S) {
      VisitedNodes.push_back("return");
      return true;
    }

    bool VisitCXXRecordDecl(CXXRecordDecl *Declaration) {
      VisitedNodes.push_back(Declaration->getQualifiedNameAsString());
      return true;
    }

    bool VisitTemplateTypeParmType(TemplateTypeParmType *T) {
      VisitedNodes.push_back(T->getDecl()->getQualifiedNameAsString());
      return true;
    }
  };

}

TEST(RecursiveASTVisitor, PostOrderTraversal) {
  auto ASTUnit = tooling::buildASTFromCode(
    "class A {"
    "  class B {"
    "    int foo() { while(4) { int i = 9; int j = -5; } return (1 + 3) + 2; }"
    "  };"
    "};"
  );
  auto TU = ASTUnit->getASTContext().getTranslationUnitDecl();
  // We traverse the translation unit and store all
  // visited nodes.
  RecordingVisitor Visitor(true);
  Visitor.TraverseTranslationUnitDecl(TU);

  std::vector<std::string> expected = {"4", "9",      "i",         "5",    "-",
                                       "j", "1",      "3",         "+",    "2",
                                       "+", "return", "A::B::foo", "A::B", "A"};
  // Compare the list of actually visited nodes
  // with the expected list of visited nodes.
  ASSERT_EQ(expected.size(), Visitor.VisitedNodes.size());
  for (std::size_t I = 0; I < expected.size(); I++) {
    ASSERT_EQ(expected[I], Visitor.VisitedNodes[I]);
  }
}

TEST(RecursiveASTVisitor, NoPostOrderTraversal) {
  auto ASTUnit = tooling::buildASTFromCode(
    "class A {"
    "  class B {"
    "    int foo() { return 1 + 2; }"
    "  };"
    "};"
  );
  auto TU = ASTUnit->getASTContext().getTranslationUnitDecl();
  // We traverse the translation unit and store all
  // visited nodes.
  RecordingVisitor Visitor(false);
  Visitor.TraverseTranslationUnitDecl(TU);

  std::vector<std::string> expected = {
    "A", "A::B", "A::B::foo", "return", "+", "1", "2"
  };
  // Compare the list of actually visited nodes
  // with the expected list of visited nodes.
  ASSERT_EQ(expected.size(), Visitor.VisitedNodes.size());
  for (std::size_t I = 0; I < expected.size(); I++) {
    ASSERT_EQ(expected[I], Visitor.VisitedNodes[I]);
  }
}
<|endoftext|>


<commit_before>//===- llvm/unittest/VMCore/InstructionsTest.cpp - Instructions unit tests ===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

#include "llvm/Instructions.h"
#include "llvm/DerivedTypes.h"
#include "llvm/LLVMContext.h"
#include "gtest/gtest.h"

namespace llvm {
namespace {

TEST(InstructionsTest, ReturnInst) {
  LLVMContext &C(getGlobalContext());

  // test for PR6589
  const ReturnInst* r0 = ReturnInst::Create(C);
  EXPECT_EQ(r0->op_begin(), r0->op_end());

  const IntegerType* Int1 = IntegerType::get(C, 1);
  Constant* One = ConstantInt::get(Int1, 1, true);
  const ReturnInst* r1 = ReturnInst::Create(C, One);
  User::const_op_iterator b(r1->op_begin());
  EXPECT_NE(b, r1->op_end());
  EXPECT_EQ(*b, One);
  EXPECT_EQ(r1->getOperand(0), One);
  ++b;
  EXPECT_EQ(b, r1->op_end());

  // clean up
  delete r0;
  delete r1;
}

}  // end anonymous namespace
}  // end namespace llvm
<commit_msg>add BranchInst tests<commit_after>//===- llvm/unittest/VMCore/InstructionsTest.cpp - Instructions unit tests ===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

#include "llvm/Instructions.h"
#include "llvm/BasicBlock.h"
#include "llvm/DerivedTypes.h"
#include "llvm/LLVMContext.h"
#include "gtest/gtest.h"

namespace llvm {
namespace {

TEST(InstructionsTest, ReturnInst) {
  LLVMContext &C(getGlobalContext());

  // test for PR6589
  const ReturnInst* r0 = ReturnInst::Create(C);
  EXPECT_EQ(r0->getNumOperands(), 0U);
  EXPECT_EQ(r0->op_begin(), r0->op_end());

  const IntegerType* Int1 = IntegerType::get(C, 1);
  Constant* One = ConstantInt::get(Int1, 1, true);
  const ReturnInst* r1 = ReturnInst::Create(C, One);
  EXPECT_EQ(r1->getNumOperands(), 1U);
  User::const_op_iterator b(r1->op_begin());
  EXPECT_NE(b, r1->op_end());
  EXPECT_EQ(*b, One);
  EXPECT_EQ(r1->getOperand(0), One);
  ++b;
  EXPECT_EQ(b, r1->op_end());

  // clean up
  delete r0;
  delete r1;
}

TEST(InstructionsTest, BranchInst) {
  LLVMContext &C(getGlobalContext());

  // Make a BasicBlocks
  BasicBlock* bb0 = BasicBlock::Create(C);
  BasicBlock* bb1 = BasicBlock::Create(C);

  // Mandatory BranchInst
  const BranchInst* b0 = BranchInst::Create(bb0);

  // check num operands
  EXPECT_EQ(b0->getNumOperands(), 1U);

  EXPECT_NE(b0->op_begin(), b0->op_end());

  const IntegerType* Int1 = IntegerType::get(C, 1);
  Constant* One = ConstantInt::get(Int1, 1, true);

  // Conditional BranchInst
  BranchInst* b1 = BranchInst::Create(bb0, bb1, One);

  // check num operands
  EXPECT_EQ(b1->getNumOperands(), 3U);

  User::const_op_iterator b(b1->op_begin());

  // check COND
  EXPECT_NE(b, b1->op_end());
  EXPECT_EQ(*b, One);
  EXPECT_EQ(b1->getOperand(0), One);
  ++b;

  // check ELSE
  EXPECT_EQ(*b, bb1);
  EXPECT_EQ(b1->getOperand(1), bb1);
  ++b;

  // check THEN
  EXPECT_EQ(*b, bb0);
  EXPECT_EQ(b1->getOperand(2), bb0);
  ++b;

  EXPECT_EQ(b, b1->op_end());

  // shrink it
  b1->setUnconditionalDest(bb1);

  // check num operands
  EXPECT_EQ(b1->getNumOperands(), 1U);

  User::const_op_iterator c(b1->op_begin());
  EXPECT_NE(c, b1->op_end());

  // check THEN
  EXPECT_EQ(*c, bb1);
  EXPECT_EQ(b1->getOperand(0), bb1);
  ++c;

  EXPECT_EQ(c, b1->op_end());

  // clean up
  delete b0;
  delete b1;

  delete bb0;
  delete bb1;
}

}  // end anonymous namespace
}  // end namespace llvm
<|endoftext|>


<commit_before>#pragma once

#include <lvtk/ui/main.hpp>
#include <lvtk/ui/widget.hpp>
#include <memory>

namespace lvtk {
namespace demo {

class Box : public lvtk::Widget {
public:
    Box() = default;
    virtual ~Box() = default;

    void paint (Graphics& g) override {
        g.set_color (color);
        g.fill_rect (bounds().at (0, 0));
    }

    bool obstructed (int x, int y) override { return true; }

    void motion (InputEvent ev) override {
        // std::clog << __name << " motion: "
        //           << ev.pos.str() << std::endl;
    }

    void pressed (InputEvent ev) override {
        std::clog << __name << "   down: "
                  << ev.pos.str() << " bounds: "
                  << bounds().str() << std::endl;
    }

    void released (InputEvent ev) override {
        std::clog << __name << "     up: "
                  << ev.pos.str() << std::endl;
    }

    Color color { 0xff0000ff };
};

class Container : public Widget {
public:
    Container() {
        add (button1);
        button1.set_visible (true);
        button1.__name = "button1";
        button1.color = Color (0x444444ff);
        add (button2);
        button2.__name = "button2";
        button2.color = button1.color;
        button2.set_visible (true);
    }

    void resized() override {
        auto r1 = bounds().at (0, 0);
        // std::clog << "container resized: " << r1.str() << std::endl;
        r1.width /= 2;
        auto r2 = r1;
        r2.x = r1.width;
        const int padding = 12;
        r1.x += padding;
        r1.y += padding;
        r1.width -= (padding * 2);
        r1.height -= (padding * 2);
        r2.x += padding;
        r2.y += padding;
        r2.width -= (padding * 2);
        r2.height -= (padding * 2);

        button1.set_bounds (r1);
        button2.set_bounds (r2);
    }

    void paint (Graphics& g) override {
        g.set_color (0x777777FF);
        g.fill_rect (bounds().at (0, 0));
    }

    Box button1, button2;
};

class Content : public Widget {
public:
    Content() {
        __name = "Content";
        add (buttons);
        buttons.set_visible (true);
        set_size (360, 240);
        set_visible (true);
    }

    ~Content() {
    }

    void motion (InputEvent ev) override {
        // std::clog << "content motion\n";
    }

    void resized() override {
        auto r = bounds().at (0, 0);
        r.x = 20;
        r.y = 20;
        r.width -= (r.x * 2);
        r.height -= (r.y * 2);
        buttons.set_bounds (r);
    }

    void paint (Graphics& g) override {
        g.set_color (Color (0x545454ff));
        g.fill_rect (bounds().at (0, 0).as<float>());
    }

private:
    Container buttons;
};

static int run (lvtk::Main& context, int argc, char** argv) {
    auto content = std::make_unique<Content>();
    content->set_size (640, 360);
    content->set_visible (true);

    try {
        context.elevate (*content, 0);
        bool quit = false;
        while (! quit) {
            context.loop (-1.0);
            quit = context.__quit_flag;
        }
    } catch (...) {
        std::clog << "fatal error in main loop\n";
        // std::clog << e.what() << std::endl;
        return 1;
    }

    content.reset();
    return 0;
}

} // namespace demo
} // namespace lvtk
<commit_msg>demo: run any widget with c++ template func<commit_after>#pragma once

#include <lvtk/ui/main.hpp>
#include <lvtk/ui/widget.hpp>
#include <memory>

namespace lvtk {
namespace demo {

class Box : public lvtk::Widget {
public:
    Box() = default;
    virtual ~Box() = default;

    void paint (Graphics& g) override {
        g.set_color (color);
        g.fill_rect (bounds().at (0, 0));
    }

    bool obstructed (int x, int y) override { return true; }

    void motion (InputEvent ev) override {
        // std::clog << __name << " motion: "
        //           << ev.pos.str() << std::endl;
    }

    void pressed (InputEvent ev) override {
        std::clog << __name << "   down: "
                  << ev.pos.str() << " bounds: "
                  << bounds().str() << std::endl;
    }

    void released (InputEvent ev) override {
        std::clog << __name << "     up: "
                  << ev.pos.str() << std::endl;
    }

    Color color { 0xff0000ff };
};

class Container : public Widget {
public:
    Container() {
        add (button1);
        button1.set_visible (true);
        button1.__name = "button1";
        button1.color = Color (0x444444ff);
        add (button2);
        button2.__name = "button2";
        button2.color = button1.color;
        button2.set_visible (true);
    }

    void resized() override {
        auto r1 = bounds().at (0, 0);
        // std::clog << "container resized: " << r1.str() << std::endl;
        r1.width /= 2;
        auto r2 = r1;
        r2.x = r1.width;
        const int padding = 12;
        r1.x += padding;
        r1.y += padding;
        r1.width -= (padding * 2);
        r1.height -= (padding * 2);
        r2.x += padding;
        r2.y += padding;
        r2.width -= (padding * 2);
        r2.height -= (padding * 2);

        button1.set_bounds (r1);
        button2.set_bounds (r2);
    }

    void paint (Graphics& g) override {
        g.set_color (0x777777FF);
        g.fill_rect (bounds().at (0, 0));
    }

    Box button1, button2;
};

class Content : public Widget {
public:
    Content() {
        __name = "Content";
        add (buttons);
        buttons.set_visible (true);
        set_size (360, 240);
        set_visible (true);
    }

    ~Content() {
    }

    void motion (InputEvent ev) override {
        // std::clog << "content motion\n";
    }

    void resized() override {
        auto r = bounds().at (0, 0);
        r.x = 20;
        r.y = 20;
        r.width -= (r.x * 2);
        r.height -= (r.y * 2);
        buttons.set_bounds (r);
    }

    void paint (Graphics& g) override {
        g.set_color (Color (0x545454ff));
        g.fill_rect (bounds().at (0, 0).as<float>());
    }

private:
    Container buttons;
};

template <class Wgt>
static int run (lvtk::Main& context) {
    auto content = std::make_unique<Wgt>();
    content->set_size (640, 360);
    content->set_visible (true);

    try {
        context.elevate (*content, 0);
        bool quit = false;
        while (! quit) {
            context.loop (-1.0);
            quit = context.__quit_flag;
        }
    } catch (...) {
        std::clog << "fatal error in main loop\n";
        // std::clog << e.what() << std::endl;
        return 1;
    }

    content.reset();
    return 0;
}

static int run (lvtk::Main& context, int, char**) {
    return run<Content> (context);
}

} // namespace demo
} // namespace lvtk
<|endoftext|>


<commit_before>/*
	This program tests class LinkedList
*/

#include<iostream>
#include<vector>
#include "linkedlist.h"

// tests insertion

void testInsert(){

	std::cout<<"Test Insert\n";

	// define vector of values
	std::vector<int> values = {6,5,4,3,2,1};

	// create linked list
	LinkedList ll;

	// insert values into linked list (always at beginning i.e. index 0)
	for(auto x: values){
		ll.insertFirst(x);
	}

	// display linked list
	ll.print();

	// insert 100 at end
	ll.insertLast(100);

	// display linked list
	ll.print();

	// insert in between
	ll.insert_node(3,5000);

	// display linked list
	ll.print();

	ll.valueAt(-500);

}

// tests valueAt() and getLength()

void testB(){

	std::cout<<"Test B\n";

	// define vector of values
	std::vector<int> values = {6,5,4,3,2,1};

	// create linked list
	LinkedList ll;

	// insert values into linked list (always at beginning i.e. index 0)
	for(auto x: values){
		ll.insertFirst(x);
	}

	// insert 100 at end
	ll.insertLast(1000);

	// insert in between
	ll.insert_node(3,5000);

	// display linked list
	ll.print();

	std::cout<<"Length: "<<ll.getLength();

	for(int i=0;i<ll.getLength();i++){

		std::cout<<"\nValut at "<<i<<": "<<ll.valueAt(i);

	}

	ll.valueAt(500);

}

// tests deletion

void testDelete(){

	std::cout<<"Test Delete\n";

	// define vector of values
	std::vector<int> values = {20,18,16,15,14,12,10,8,6,4,1,2,0};

	// Create linked list
	LinkedList ll;

	for(auto x: values){

		ll.insertFirst(x);
	}

	ll.print();

	std::cout<<"\nDelete index: 9\n";
	ll.delete_node(9);
	ll.print();

	std::cout<<"\nDelete index : 2\n";
	ll.delete_node(2);
	ll.print();

	std::cout<<"\nDelete index: 0\n";
	ll.delete_node(0);
	ll.print();

	std::cout<<"\nDelete index: 9\n";
	ll.delete_node(9);
	ll.print();

}

// tests reverse
void testReverse(){

	std::cout<<"Test Reverse\n";

	// define vector of values
	std::vector<int> values = {10,9,8,7,6,5,4,3,2,1};

	// Create linked list
	LinkedList ll;

	for(auto x: values){

		ll.insertFirst(x);
	}

	ll.print();

	ll.reverse();

	ll.print();

	ll.delete_node(0);

	ll.print();

	ll.reverse();

	ll.print();

	for(int i=0;i<7;i++)
		ll.delete_node(0);

	ll.print();

	ll.reverse();

	ll.print();

	ll.delete_node(0);

	ll.print();

	ll.reverse();

	ll.print();

	ll.delete_node(0);

	ll.print();

	ll.reverse();

	ll.print();

}

// tests pairwiseReverse
void testpairwiseReverse(){

	std::cout<<"Test Pairwise Reverse\n";

	// define vector of values
	std::vector<int> values = {10,9,8,7,6,5,4,3,2,1};

	// Create linked list
	LinkedList ll;

	for(auto x: values){

		ll.insertFirst(x);
	}

	ll.print();

	ll.pairwiseReverse();

	ll.print();

	ll.delete_node(0);

	ll.print();

	ll.pairwiseReverse();

	ll.print();

	for(int i=0;i<6;i++)
		ll.delete_node(0);

	ll.print();

	ll.pairwiseReverse();

	ll.print();

	ll.delete_node(0);

	ll.print();

	ll.pairwiseReverse();

	ll.print();

	ll.delete_node(0);

	ll.print();

	ll.pairwiseReverse();

	ll.print();

}

// tests hasLoop

void testHasLoop(){

	LinkedList l1(1);

	if(l1.hasLoop()!=nullptr)
		std::cout<<"\nl1 has loop";
	else
		std::cout<<"\nl1 does not have loop";

	LinkedList l2;
	for(int i=1;i<=5;i++)
		l2.insertLast(i);

	if(l2.hasLoop()!=nullptr)
		std::cout<<"\nl2 has loop";
	else
		std::cout<<"\nl2 does not have loop";

	LinkedList l3(2);

	if(l3.hasLoop()!=nullptr)
		std::cout<<"\nl3 has loop";
	else
		std::cout<<"\nl3 does not have loop";

	LinkedList l4(3);

	if(l4.hasLoop()!=nullptr)
		std::cout<<"\nl4 has loop";
	else
		std::cout<<"\nl4 does not have loop";
}

int main(){

	// test insert
	testInsert();

	// test B
	testB();

	// test delete
	testDelete();

	// test reverse
	testReverse();

	// test pairwise reverse
	testpairwiseReverse();

	// test hasLoop
	testHasLoop();

	return 0;
}
<commit_msg>Add test cases for loop removal<commit_after>/*
	This program tests class LinkedList
*/

#include<iostream>
#include<vector>
#include "linkedlist.h"

// tests insertion

void testInsert(){

	std::cout<<"Test Insert\n";

	// define vector of values
	std::vector<int> values = {6,5,4,3,2,1};

	// create linked list
	LinkedList ll;

	// insert values into linked list (always at beginning i.e. index 0)
	for(auto x: values){
		ll.insertFirst(x);
	}

	// display linked list
	ll.print();

	// insert 100 at end
	ll.insertLast(100);

	// display linked list
	ll.print();

	// insert in between
	ll.insert_node(3,5000);

	// display linked list
	ll.print();

	ll.valueAt(-500);

}

// tests valueAt() and getLength()

void testB(){

	std::cout<<"Test B\n";

	// define vector of values
	std::vector<int> values = {6,5,4,3,2,1};

	// create linked list
	LinkedList ll;

	// insert values into linked list (always at beginning i.e. index 0)
	for(auto x: values){
		ll.insertFirst(x);
	}

	// insert 100 at end
	ll.insertLast(1000);

	// insert in between
	ll.insert_node(3,5000);

	// display linked list
	ll.print();

	std::cout<<"Length: "<<ll.getLength();

	for(int i=0;i<ll.getLength();i++){

		std::cout<<"\nValut at "<<i<<": "<<ll.valueAt(i);

	}

	ll.valueAt(500);

}

// tests deletion

void testDelete(){

	std::cout<<"Test Delete\n";

	// define vector of values
	std::vector<int> values = {20,18,16,15,14,12,10,8,6,4,1,2,0};

	// Create linked list
	LinkedList ll;

	for(auto x: values){

		ll.insertFirst(x);
	}

	ll.print();

	std::cout<<"\nDelete index: 9\n";
	ll.delete_node(9);
	ll.print();

	std::cout<<"\nDelete index : 2\n";
	ll.delete_node(2);
	ll.print();

	std::cout<<"\nDelete index: 0\n";
	ll.delete_node(0);
	ll.print();

	std::cout<<"\nDelete index: 9\n";
	ll.delete_node(9);
	ll.print();

}

// tests reverse
void testReverse(){

	std::cout<<"Test Reverse\n";

	// define vector of values
	std::vector<int> values = {10,9,8,7,6,5,4,3,2,1};

	// Create linked list
	LinkedList ll;

	for(auto x: values){

		ll.insertFirst(x);
	}

	ll.print();

	ll.reverse();

	ll.print();

	ll.delete_node(0);

	ll.print();

	ll.reverse();

	ll.print();

	for(int i=0;i<7;i++)
		ll.delete_node(0);

	ll.print();

	ll.reverse();

	ll.print();

	ll.delete_node(0);

	ll.print();

	ll.reverse();

	ll.print();

	ll.delete_node(0);

	ll.print();

	ll.reverse();

	ll.print();

}

// tests pairwiseReverse
void testpairwiseReverse(){

	std::cout<<"Test Pairwise Reverse\n";

	// define vector of values
	std::vector<int> values = {10,9,8,7,6,5,4,3,2,1};

	// Create linked list
	LinkedList ll;

	for(auto x: values){

		ll.insertFirst(x);
	}

	ll.print();

	ll.pairwiseReverse();

	ll.print();

	ll.delete_node(0);

	ll.print();

	ll.pairwiseReverse();

	ll.print();

	for(int i=0;i<6;i++)
		ll.delete_node(0);

	ll.print();

	ll.pairwiseReverse();

	ll.print();

	ll.delete_node(0);

	ll.print();

	ll.pairwiseReverse();

	ll.print();

	ll.delete_node(0);

	ll.print();

	ll.pairwiseReverse();

	ll.print();

}

// tests hasLoop

void testHasLoop(){

	LinkedList l1(1);

	if(l1.hasLoop()!=nullptr)
		std::cout<<"\nl1 has loop";
	else
		std::cout<<"\nl1 does not have loop";

	LinkedList l2;
	for(int i=1;i<=5;i++)
		l2.insertLast(i);

	if(l2.hasLoop()!=nullptr)
		std::cout<<"\nl2 has loop";
	else
		std::cout<<"\nl2 does not have loop";

	LinkedList l3(2);

	if(l3.hasLoop()!=nullptr)
		std::cout<<"\nl3 has loop";
	else
		std::cout<<"\nl3 does not have loop";

	LinkedList l4(3);

	if(l4.hasLoop()!=nullptr)
		std::cout<<"\nl4 has loop";
	else
		std::cout<<"\nl4 does not have loop";
}

//tests remove loop

void testRemoveLoop(){

	LinkedList l1(1);

	Node * loopnode1 = l1.hasLoop();

	if(loopnode1!=nullptr)
		std::cout<<"\nl1 has loop";
	else
		std::cout<<"\nl1 does not have loop";

	l1.removeLoop(loopnode1);

	loopnode1 = l1.hasLoop();

	if(loopnode1!=nullptr)
		std::cout<<"\nl1 has loop";
	else
		std::cout<<"\nl1 does not have loop";

	l1.print();

	LinkedList l3(2);

	Node * loopnode3 = l3.hasLoop();

	if(loopnode3!=nullptr)
		std::cout<<"\nl3 has loop";
	else
		std::cout<<"\nl3 does not have loop";

	l3.removeLoop(loopnode3);

	loopnode3 = l3.hasLoop();

	if(loopnode3!=nullptr)
		std::cout<<"\nl3 has loop";
	else
		std::cout<<"\nl3 does not have loop";

	l3.print();

	LinkedList l4(3);

	Node *loopnode4 = l4.hasLoop();

	if(loopnode4!=nullptr)
		std::cout<<"\nl4 has loop";
	else
		std::cout<<"\nl4 does not have loop";

	l4.removeLoop(loopnode4);

	loopnode4 = l4.hasLoop();

	if(loopnode4!=nullptr)
		std::cout<<"\nl4 has loop";
	else
		std::cout<<"\nl4 does not have loop";

	l4.print();

}

int main(){

	// test insert
	testInsert();

	// test B
	testB();

	// test delete
	testDelete();

	// test reverse
	testReverse();

	// test pairwise reverse
	testpairwiseReverse();

	// test hasLoop
	testHasLoop();

	// test remove loop
	testRemoveLoop();

	return 0;
}
<|endoftext|>


<commit_before>/*
 * Copyright 2014 Open Connectome Project (http://openconnecto.me)
 * Written by Da Zheng (zhengda1936@gmail.com)
 *
 * This file is part of FlashMatrix.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include <unordered_map>

#include "io_interface.h"

#include "matrix_config.h"
#include "mem_worker_thread.h"
#include "EM_object.h"
#include "local_mem_buffer.h"

namespace fm
{

namespace detail
{

#ifdef USE_HWLOC
std::vector<int> get_cpus(int node_id)
{
	std::vector<int> io_cpus = safs::get_io_cpus();
	std::vector<int> logical_units = cpus.get_node(node_id).get_logical_units();
	std::set<int> cpu_set(logical_units.begin(), logical_units.end());
	// Remove the logical units where I/O threads run.
	for (size_t j = 0; j < io_cpus.size(); j++)
		cpu_set.erase(io_cpus[j]);
	return std::vector<int>(cpu_set.begin(), cpu_set.end());
}
#endif

mem_thread_pool::mem_thread_pool(int num_nodes, int nthreads_per_node)
{
	tot_num_tasks = 0;
	threads.resize(num_nodes);
	for (int i = 0; i < num_nodes; i++) {
		// Get the CPU cores that are in node i.
#ifdef USE_HWLOC
		std::vector<int> cpus = get_cpus(i);
#endif
		threads[i].resize(nthreads_per_node);
		for (int j = 0; j < nthreads_per_node; j++) {
			std::string name
				= std::string("mem-worker-") + itoa(i) + "-" + itoa(j);
#ifdef USE_HWLOC
			if (safs::get_io_cpus().empty())
				threads[i][j] = std::shared_ptr<pool_task_thread>(
						new pool_task_thread(i * nthreads_per_node + j, name, i));
			else
				threads[i][j] = std::shared_ptr<pool_task_thread>(
						new pool_task_thread(i * nthreads_per_node + j, name,
							cpus, i));
#else
			threads[i][j] = std::shared_ptr<pool_task_thread>(
					new pool_task_thread(i * nthreads_per_node + j, name, i));
#endif
			threads[i][j]->start();
		}
	}
	ntasks_per_node.resize(num_nodes);
}

/*
 * This method dispatches tasks in a round-robin fashion.
 */
void mem_thread_pool::process_task(int node_id, thread_task *task)
{
	if (node_id < 0)
		node_id = tot_num_tasks % get_num_nodes();

	assert((size_t) node_id < threads.size());
	size_t idx = ntasks_per_node[node_id] % threads[node_id].size();
	threads[node_id][idx]->add_task(task);
	ntasks_per_node[node_id]++;
	tot_num_tasks++;
}

void mem_thread_pool::wait4complete()
{
	for (size_t i = 0; i < threads.size(); i++) {
		size_t nthreads = threads[i].size();
		for (size_t j = 0; j < nthreads; j++)
			threads[i][j]->wait4complete();
	}

	// After all workers complete, we should try to clear the memory buffers
	// in each worker thread to reduce memory consumption.
	// We might want to keep the memory buffer for I/O on dense matrices.
	if (matrix_conf.is_keep_mem_buf())
		detail::local_mem_buffer::clear_bufs(
				detail::local_mem_buffer::MAT_PORTION);
	else
		detail::local_mem_buffer::clear_bufs();
}

size_t mem_thread_pool::get_num_pending() const
{
	size_t ret = 0;
	for (size_t i = 0; i < threads.size(); i++) {
		size_t nthreads = threads[i].size();
		for (size_t j = 0; j < nthreads; j++)
			ret += threads[i][j]->get_num_pending();
	}
	return ret;
}

static mem_thread_pool::ptr global_threads;
enum thread_pool_state {
	UNINIT,
	ACTIVE,
	INACTIVE,
};
static thread_pool_state pool_state = thread_pool_state::UNINIT;

/*
 * When we disable thread pool, we use the main thread to perform
 * computation.
 */
bool mem_thread_pool::disable_thread_pool()
{
	pool_state = thread_pool_state::INACTIVE;
	return true;
}

bool mem_thread_pool::enable_thread_pool()
{
	pool_state = thread_pool_state::ACTIVE;
	return true;
}

mem_thread_pool::ptr mem_thread_pool::get_global_mem_threads()
{
	assert(pool_state != thread_pool_state::INACTIVE);
	if (global_threads == NULL) {
		int nthreads_per_node
			= matrix_conf.get_num_DM_threads() / matrix_conf.get_num_nodes();
		assert(nthreads_per_node > 0);
		global_threads = mem_thread_pool::create(matrix_conf.get_num_nodes(),
				nthreads_per_node);
		enable_thread_pool();
	}
	return global_threads;
}

size_t mem_thread_pool::get_global_num_threads()
{
	// When we disable the thread pool, we use the main thread for computation.
	// So the number of threads is 1.
	if (pool_state == thread_pool_state::INACTIVE)
		return 1;
	else
		return get_global_mem_threads()->get_num_threads();
}

int mem_thread_pool::get_curr_thread_id()
{
	// When we disable the thread pool, we use the main thread for computation.
	// And we use 0 as the thread id of the main thread.
	if (pool_state == thread_pool_state::INACTIVE)
		return 0;
	else {
		detail::pool_task_thread *curr
			= dynamic_cast<detail::pool_task_thread *>(thread::get_curr_thread());
		assert(curr);
		return curr->get_pool_thread_id();
	}
}

void mem_thread_pool::init_global_mem_threads(int num_nodes,
		int nthreads_per_node)
{
	if (global_threads == NULL) {
		global_threads = mem_thread_pool::create(num_nodes, nthreads_per_node);
		enable_thread_pool();
	}
}

void mem_thread_pool::destroy()
{
	global_threads = NULL;
}

static size_t wait4ios(safs::io_select::ptr select, size_t max_pending_ios)
{
	size_t num_pending;
	do {
		num_pending = select->num_pending_ios();

		// Figure out how many I/O requests we have to wait for in
		// this iteration.
		int num_to_process;
		if (num_pending > max_pending_ios)
			num_to_process = num_pending - max_pending_ios;
		else
			num_to_process = 0;
		select->wait4complete(num_to_process);

		// Test if all I/O instances have pending I/O requests left.
		// When a portion of a matrix is ready in memory and being processed,
		// it may result in writing data to another matrix. Therefore, we
		// need to process all completed I/O requests (portions with data
		// in memory) first and then count the number of new pending I/Os.
		num_pending = select->num_pending_ios();
	} while (num_pending > max_pending_ios);
	return num_pending;
}

void io_worker_task::run()
{
	std::vector<safs::io_interface::ptr> ios;
	pthread_spin_lock(&lock);
	for (auto it = EM_objs.begin(); it != EM_objs.end(); it++) {
		std::vector<safs::io_interface::ptr> tmp = (*it)->create_ios();
		ios.insert(ios.end(), tmp.begin(), tmp.end());
	}
	pthread_spin_unlock(&lock);
	safs::io_select::ptr select = safs::create_io_select(ios);

	// The task runs until there are no tasks left in the queue.
	while (dispatch->issue_task())
		wait4ios(select, max_pending_ios);
	// Test if all I/O instances have processed all requests.
	size_t num_pending = wait4ios(select, 0);
	assert(num_pending == 0);

	pthread_spin_lock(&lock);
	EM_objs.clear();
	pthread_spin_unlock(&lock);

	for (size_t i = 0; i < ios.size(); i++) {
		portion_callback &cb = static_cast<portion_callback &>(
				ios[i]->get_callback());
		assert(!cb.has_callback());
	}
}

global_counter::global_counter()
{
	counts.resize(mem_thread_pool::get_global_num_threads());
	reset();
}

void global_counter::inc(size_t val)
{
	int id = mem_thread_pool::get_curr_thread_id();
	counts[id].count += val;
}

void global_counter::reset()
{
	for (size_t i = 0; i < counts.size(); i++)
		counts[i].count = 0;
}

size_t global_counter::get() const
{
	size_t tot = 0;
	for (size_t i = 0; i < counts.size(); i++)
		tot += counts[i].count;
	return tot;
}

}

}
<commit_msg>[Matrix]: del wait4ios.<commit_after>/*
 * Copyright 2014 Open Connectome Project (http://openconnecto.me)
 * Written by Da Zheng (zhengda1936@gmail.com)
 *
 * This file is part of FlashMatrix.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include <unordered_map>

#include "io_interface.h"

#include "matrix_config.h"
#include "mem_worker_thread.h"
#include "EM_object.h"
#include "local_mem_buffer.h"

namespace fm
{

namespace detail
{

#ifdef USE_HWLOC
std::vector<int> get_cpus(int node_id)
{
	std::vector<int> io_cpus = safs::get_io_cpus();
	std::vector<int> logical_units = cpus.get_node(node_id).get_logical_units();
	std::set<int> cpu_set(logical_units.begin(), logical_units.end());
	// Remove the logical units where I/O threads run.
	for (size_t j = 0; j < io_cpus.size(); j++)
		cpu_set.erase(io_cpus[j]);
	return std::vector<int>(cpu_set.begin(), cpu_set.end());
}
#endif

mem_thread_pool::mem_thread_pool(int num_nodes, int nthreads_per_node)
{
	tot_num_tasks = 0;
	threads.resize(num_nodes);
	for (int i = 0; i < num_nodes; i++) {
		// Get the CPU cores that are in node i.
#ifdef USE_HWLOC
		std::vector<int> cpus = get_cpus(i);
#endif
		threads[i].resize(nthreads_per_node);
		for (int j = 0; j < nthreads_per_node; j++) {
			std::string name
				= std::string("mem-worker-") + itoa(i) + "-" + itoa(j);
#ifdef USE_HWLOC
			if (safs::get_io_cpus().empty())
				threads[i][j] = std::shared_ptr<pool_task_thread>(
						new pool_task_thread(i * nthreads_per_node + j, name, i));
			else
				threads[i][j] = std::shared_ptr<pool_task_thread>(
						new pool_task_thread(i * nthreads_per_node + j, name,
							cpus, i));
#else
			threads[i][j] = std::shared_ptr<pool_task_thread>(
					new pool_task_thread(i * nthreads_per_node + j, name, i));
#endif
			threads[i][j]->start();
		}
	}
	ntasks_per_node.resize(num_nodes);
}

/*
 * This method dispatches tasks in a round-robin fashion.
 */
void mem_thread_pool::process_task(int node_id, thread_task *task)
{
	if (node_id < 0)
		node_id = tot_num_tasks % get_num_nodes();

	assert((size_t) node_id < threads.size());
	size_t idx = ntasks_per_node[node_id] % threads[node_id].size();
	threads[node_id][idx]->add_task(task);
	ntasks_per_node[node_id]++;
	tot_num_tasks++;
}

void mem_thread_pool::wait4complete()
{
	for (size_t i = 0; i < threads.size(); i++) {
		size_t nthreads = threads[i].size();
		for (size_t j = 0; j < nthreads; j++)
			threads[i][j]->wait4complete();
	}

	// After all workers complete, we should try to clear the memory buffers
	// in each worker thread to reduce memory consumption.
	// We might want to keep the memory buffer for I/O on dense matrices.
	if (matrix_conf.is_keep_mem_buf())
		detail::local_mem_buffer::clear_bufs(
				detail::local_mem_buffer::MAT_PORTION);
	else
		detail::local_mem_buffer::clear_bufs();
}

size_t mem_thread_pool::get_num_pending() const
{
	size_t ret = 0;
	for (size_t i = 0; i < threads.size(); i++) {
		size_t nthreads = threads[i].size();
		for (size_t j = 0; j < nthreads; j++)
			ret += threads[i][j]->get_num_pending();
	}
	return ret;
}

static mem_thread_pool::ptr global_threads;
enum thread_pool_state {
	UNINIT,
	ACTIVE,
	INACTIVE,
};
static thread_pool_state pool_state = thread_pool_state::UNINIT;

/*
 * When we disable thread pool, we use the main thread to perform
 * computation.
 */
bool mem_thread_pool::disable_thread_pool()
{
	pool_state = thread_pool_state::INACTIVE;
	return true;
}

bool mem_thread_pool::enable_thread_pool()
{
	pool_state = thread_pool_state::ACTIVE;
	return true;
}

mem_thread_pool::ptr mem_thread_pool::get_global_mem_threads()
{
	assert(pool_state != thread_pool_state::INACTIVE);
	if (global_threads == NULL) {
		int nthreads_per_node
			= matrix_conf.get_num_DM_threads() / matrix_conf.get_num_nodes();
		assert(nthreads_per_node > 0);
		global_threads = mem_thread_pool::create(matrix_conf.get_num_nodes(),
				nthreads_per_node);
		enable_thread_pool();
	}
	return global_threads;
}

size_t mem_thread_pool::get_global_num_threads()
{
	// When we disable the thread pool, we use the main thread for computation.
	// So the number of threads is 1.
	if (pool_state == thread_pool_state::INACTIVE)
		return 1;
	else
		return get_global_mem_threads()->get_num_threads();
}

int mem_thread_pool::get_curr_thread_id()
{
	// When we disable the thread pool, we use the main thread for computation.
	// And we use 0 as the thread id of the main thread.
	if (pool_state == thread_pool_state::INACTIVE)
		return 0;
	else {
		detail::pool_task_thread *curr
			= dynamic_cast<detail::pool_task_thread *>(thread::get_curr_thread());
		assert(curr);
		return curr->get_pool_thread_id();
	}
}

void mem_thread_pool::init_global_mem_threads(int num_nodes,
		int nthreads_per_node)
{
	if (global_threads == NULL) {
		global_threads = mem_thread_pool::create(num_nodes, nthreads_per_node);
		enable_thread_pool();
	}
}

void mem_thread_pool::destroy()
{
	global_threads = NULL;
}

void io_worker_task::run()
{
	std::vector<safs::io_interface::ptr> ios;
	pthread_spin_lock(&lock);
	for (auto it = EM_objs.begin(); it != EM_objs.end(); it++) {
		std::vector<safs::io_interface::ptr> tmp = (*it)->create_ios();
		ios.insert(ios.end(), tmp.begin(), tmp.end());
	}
	pthread_spin_unlock(&lock);
	safs::io_select::ptr select = safs::create_io_select(ios);

	// The task runs until there are no tasks left in the queue.
	while (dispatch->issue_task())
		safs::wait4ios(select, max_pending_ios);
	// Test if all I/O instances have processed all requests.
	size_t num_pending = safs::wait4ios(select, 0);
	assert(num_pending == 0);

	pthread_spin_lock(&lock);
	EM_objs.clear();
	pthread_spin_unlock(&lock);

	for (size_t i = 0; i < ios.size(); i++) {
		portion_callback &cb = static_cast<portion_callback &>(
				ios[i]->get_callback());
		assert(!cb.has_callback());
	}
}

global_counter::global_counter()
{
	counts.resize(mem_thread_pool::get_global_num_threads());
	reset();
}

void global_counter::inc(size_t val)
{
	int id = mem_thread_pool::get_curr_thread_id();
	counts[id].count += val;
}

void global_counter::reset()
{
	for (size_t i = 0; i < counts.size(); i++)
		counts[i].count = 0;
}

size_t global_counter::get() const
{
	size_t tot = 0;
	for (size_t i = 0; i < counts.size(); i++)
		tot += counts[i].count;
	return tot;
}

}

}
<|endoftext|>


<commit_before>#ifndef UNITTEST11_UTILITY_TOSTRING_HPP
#define UNITTEST11_UTILITY_TOSTRING_HPP

#include "Meta/IsIterableContainer.hpp"
#include "Meta/IfElseTypes.hpp"

#include <memory>
#include <string>
#include <sstream>

namespace ut11
{
	namespace utility
	{
		template<typename V> inline std::string ToString(const V& value);

		namespace detail
		{
			template<typename S, typename T>
			class IsStreamWritable
			{
				template<typename SS, typename TT>
				static auto test(int) -> decltype(std::declval<SS&>() << std::declval<TT>(), std::true_type());

				template<typename, typename> static auto test(...) -> std::false_type;

			public:
				typedef decltype(test<S, T>(0)) Result;
			};

			template<typename V> struct ParseNonIterableToString
			{
				inline std::string operator()(const V& value) const
				{
					return ToString(value, IsStreamWritable<std::stringstream, V>::Result());
				}

				inline std::string ToString(const V& value, std::true_type) const
				{
					std::stringstream stream;
					stream << value;
					return stream.str();
				}

				inline std::string ToString(const V& value, std::false_type) const
				{
					std::stringstream stream;
					stream << "[" << typeid(V).name() << "]";
					return stream.str();
				}
			};

			template<typename V> struct ParseIterableToString
			{
				inline std::string operator()(const V& value) const
				{
					std::stringstream stream;
					stream << "{ ";
					for (const auto& arg : value)
						stream << ToString(arg) << " ";
					stream << "}";
					return stream.str();
				}
			};
		}

		/*! \brief Can be partially specialised to parse non-streamables to strings without making the type streamable */
		template<typename V> struct ParseToString
		{
			inline std::string operator()(const V& value) const
			{
				return typename Meta::IfElseTypes< Meta::IsIterableContainer<V>::value, detail::ParseIterableToString<V>, detail::ParseNonIterableToString<V> >::type()(value);
			}
		};

		template<> struct ParseToString<std::string>
		{
			inline std::string operator()(const std::string& value) const
			{
				return value;
			}
		};

		template<> struct ParseToString< void* >
		{
			inline std::string operator()(void* value) const
			{
				return value ? std::string("void_pointer:") + detail::ParseNonIterableToString<void*>()(value) : "nullptr";
			}
		};
		template<typename T> struct ParseToString< T* >
		{
			inline std::string operator()(T* value) const
			{
				return value ? std::string("pointer:") + ParseToString<T>()(*value) : "nullptr";
			}
		};

		template<typename T, typename U> struct ParseToString< std::unique_ptr<T,U> >
		{
			inline std::string operator()(const std::unique_ptr<T,U>& value) const
			{
				return value ? std::string("unique_ptr:") + ParseToString<T>()(*value) : "nullptr";
			}
		};

		template<> struct ParseToString< std::shared_ptr<void> >
		{
			inline std::string operator()(const std::shared_ptr<void>& value) const
			{
				return value ? std::string("shared_ptr<void>:") + detail::ParseNonIterableToString<void*>()(value.get()) : "nullptr";
			}
		};
		template<typename T> struct ParseToString< std::shared_ptr<T> >
		{
			inline std::string operator()(const std::shared_ptr<T>& value) const
			{
				return value ? std::string("shared_ptr:") + ParseToString<T>()(*value) : "nullptr";
			}
		};

		template<typename V> inline std::string ToString(const V& value)
		{
			return ParseToString<V>()(value);
		}
	}
}

#endif // UNITTEST11_UTILITY_TOSTRING_HPP
<commit_msg>Fixed in gcc<commit_after>#ifndef UNITTEST11_UTILITY_TOSTRING_HPP
#define UNITTEST11_UTILITY_TOSTRING_HPP

#include "Meta/IsIterableContainer.hpp"
#include "Meta/IfElseTypes.hpp"

#include <memory>
#include <string>
#include <sstream>

namespace ut11
{
	namespace utility
	{
		template<typename V> inline std::string ToString(const V& value);

		namespace detail
		{
			template<typename S, typename T>
			class IsStreamWritable
			{
				template<typename SS, typename TT>
				static auto test(int) -> decltype(std::declval<SS&>() << std::declval<TT>(), std::true_type());

				template<typename, typename> static auto test(...) -> std::false_type;

			public:
				typedef decltype(test<S, T>(0)) Result;
			};

			template<typename V> struct ParseNonIterableToString
			{
				inline std::string operator()(const V& value) const
				{
					return ToString(value, typename IsStreamWritable<std::stringstream, V>::Result());
				}

				inline std::string ToString(const V& value, std::true_type) const
				{
					std::stringstream stream;
					stream << value;
					return stream.str();
				}

				inline std::string ToString(const V& value, std::false_type) const
				{
					std::stringstream stream;
					stream << "[" << typeid(V).name() << "]";
					return stream.str();
				}
			};

			template<typename V> struct ParseIterableToString
			{
				inline std::string operator()(const V& value) const
				{
					std::stringstream stream;
					stream << "{ ";
					for (const auto& arg : value)
						stream << ToString(arg) << " ";
					stream << "}";
					return stream.str();
				}
			};
		}

		/*! \brief Can be partially specialised to parse non-streamables to strings without making the type streamable */
		template<typename V> struct ParseToString
		{
			inline std::string operator()(const V& value) const
			{
				return typename Meta::IfElseTypes< Meta::IsIterableContainer<V>::value, detail::ParseIterableToString<V>, detail::ParseNonIterableToString<V> >::type()(value);
			}
		};

		template<> struct ParseToString<std::string>
		{
			inline std::string operator()(const std::string& value) const
			{
				return value;
			}
		};

		template<> struct ParseToString< void* >
		{
			inline std::string operator()(void* value) const
			{
				return value ? std::string("void_pointer:") + detail::ParseNonIterableToString<void*>()(value) : "nullptr";
			}
		};
		template<typename T> struct ParseToString< T* >
		{
			inline std::string operator()(T* value) const
			{
				return value ? std::string("pointer:") + ParseToString<T>()(*value) : "nullptr";
			}
		};

		template<typename T, typename U> struct ParseToString< std::unique_ptr<T,U> >
		{
			inline std::string operator()(const std::unique_ptr<T,U>& value) const
			{
				return value ? std::string("unique_ptr:") + ParseToString<T>()(*value) : "nullptr";
			}
		};

		template<> struct ParseToString< std::shared_ptr<void> >
		{
			inline std::string operator()(const std::shared_ptr<void>& value) const
			{
				return value ? std::string("shared_ptr<void>:") + detail::ParseNonIterableToString<void*>()(value.get()) : "nullptr";
			}
		};
		template<typename T> struct ParseToString< std::shared_ptr<T> >
		{
			inline std::string operator()(const std::shared_ptr<T>& value) const
			{
				return value ? std::string("shared_ptr:") + ParseToString<T>()(*value) : "nullptr";
			}
		};

		template<typename V> inline std::string ToString(const V& value)
		{
			return ParseToString<V>()(value);
		}
	}
}

#endif // UNITTEST11_UTILITY_TOSTRING_HPP
<|endoftext|>