<commit_before>/*
   For more information, please see: http://software.sci.utah.edu

   The MIT License

   Copyright (c) 2012 Scientific Computing and Imaging Institute,
   University of Utah.

   License for the specific language governing rights and limitations under
   Permission is hereby granted, free of charge, to any person obtaining a
   copy of this software and associated documentation files (the "Software"),
   to deal in the Software without restriction, including without limitation
   the rights to use, copy, modify, merge, publish, distribute, sublicense,
   and/or sell copies of the Software, and to permit persons to whom the
   Software is furnished to do so, subject to the following conditions:

   The above copyright notice and this permission notice shall be included
   in all copies or substantial portions of the Software.

   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
   OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
   FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
   THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
   LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
   FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
   DEALINGS IN THE SOFTWARE.
*/

#include <gtest/gtest.h>
#include <gmock/gmock.h>

#include <Core/Datatypes/Legacy/Field/VField.h>
#include <Core/Datatypes/Legacy/Field/FieldInformation.h>
#include <Core/Datatypes/Matrix.h>
#include <Core/Algorithms/Base/AlgorithmPreconditions.h>
#include <Core/Algorithms/Legacy/Fields/MergeFields/JoinFieldsAlgo.h>
#include <Core/Algorithms/Base/AlgorithmVariableNames.h>
#include <Testing/Utils/SCIRunUnitTests.h>
#include <Testing/Utils/MatrixTestUtilities.h>
#include <Core/Logging/Log.h>

using namespace SCIRun;
using namespace SCIRun::Core::Datatypes;
using namespace SCIRun::Core::Geometry;
using namespace SCIRun::Core::Algorithms::Fields;
using namespace SCIRun::TestUtils;
using ::testing::NotNull;
using ::testing::TestWithParam;
using ::testing::Values;

class JoinFieldsAlgoTests : public ::testing::Test
{
protected:
  virtual void SetUp()
  {
    SCIRun::Core::Logging::Log::get().setVerbose(true);
  }

  FieldHandle CreateEmptyLatVol(size_type sizex = 3, size_type sizey = 4, size_type sizez = 5)
  {
    FieldInformation lfi("LatVolMesh", 1, "double");
    Point minb(-1.0, -1.0, -1.0);
    Point maxb(1.0, 1.0, 1.0);
    MeshHandle mesh = CreateMesh(lfi,sizex, sizey, sizez, minb, maxb);
    FieldHandle ofh = CreateField(lfi,mesh);
    ofh->vfield()->clear_all_values();
    return ofh;
  }
};

// parameters:
// MergeNodes = Bool()
// MergeElems = Bool()
// MatchNodeValues = Bool()
// MakeNoData = Bool()
// Tolerance = Values(1e-1, 1e-3, ...)

TEST_F(JoinFieldsAlgoTests, CanLogErrorMessage)
{
  JoinFieldsAlgo algo;
  FieldList input;
  FieldHandle output;
  EXPECT_FALSE(algo.runImpl(input, output));
}

TEST_F(JoinFieldsAlgoTests, CanJoinMultipleLatVols)
{
  JoinFieldsAlgo algo;

  FieldList input;
  input.push_back(CreateEmptyLatVol(2,3,4));
  EXPECT_EQ(2*3*4, input[0]->vmesh()->num_nodes());
  input.push_back(CreateEmptyLatVol(5,6,7));
  EXPECT_EQ(5*6*7, input[1]->vmesh()->num_nodes());
  input.push_back(CreateEmptyLatVol(8,9,10));
  EXPECT_EQ(8*9*10, input[2]->vmesh()->num_nodes());

  FieldHandle output;
  EXPECT_TRUE(algo.runImpl(input, output));
  EXPECT_EQ(914, output->vmesh()->num_nodes());

  input.push_back(CreateEmptyLatVol(11,12,13));
  EXPECT_EQ(11*12*13, input[3]->vmesh()->num_nodes());
  EXPECT_TRUE(algo.runImpl(input, output));
  EXPECT_EQ(2588, output->vmesh()->num_nodes());
}

TEST_F(JoinFieldsAlgoTests, CanJoinMultipleLatVolsGeneric)
{
  JoinFieldsAlgo algo;

  FieldList input;
  input.push_back(CreateEmptyLatVol(2,3,4));
  input.push_back(CreateEmptyLatVol(5,6,7));
  input.push_back(CreateEmptyLatVol(8,9,10));

  auto outputObj = algo.run_generic(make_input((JoinFieldsAlgo::InputFields, input)));

  FieldHandle output = outputObj.get<Field>(Core::Algorithms::Variables::OutputField);
  EXPECT_EQ(914, output->vmesh()->num_nodes());
}

#if SCIRUN4_CODE_TO_BE_ENABLED_LATER

#if GTEST_HAS_COMBINE

/*Get Parameterized Tests
*/
using ::testing::Bool;
using ::testing::Values;
using ::testing::Combine;

class JoinFieldsAlgoTestsParameterized : public ::testing::TestWithParam < ::std::tr1::tuple<bool, bool, bool, bool, bool, double> >
{
public:
  FieldHandle latVol1_;
  FieldHandle latVol2_;

  JoinFieldsAlgo algo_;
  FieldList fieldList_;

  JoinFieldsAlgoTestsParameterized()
  {
    latVol1_ = loadFieldFromFile(TestResources::rootDir() / "latVolWithNormData.fld");
    SCIRun::Core::Logging::Log::get().setVerbose(true);
  }

protected:
  virtual void SetUp()
  {
	FieldList fl;
	//create 2 latVol's
	//SCIRun::Modules::Fields lv1;
	//CreateLatVol() lv2;

	//lv1.set(lv1.XSize(2));

    ASSERT_TRUE(latVol1_->vmesh()->is_latvolmesh());
    // How to set parameters on an algorithm (that come from the GUI)
    algo_.set(algo_.MergeNodes,      ::std::tr1::get<0>(GetParam()));
	algo_.set(algo_.MergeElems,      ::std::tr1::get<1>(GetParam()));
    algo_.set(algo_.InputFields,     ::std::tr1::get<2>(GetParam()));
    algo_.set(algo_.MatchNodeValues, ::std::tr1::get<3>(GetParam()));
    algo_.set(algo_.MakeNoData,      ::std::tr1::get<4>(GetParam()));
    algo_.set(algo_.Tolerance,       ::std::tr1::get<5>(GetParam()));
  }
  virtual void TearDown()
  {  }

};

TEST_P(JoinFieldsAlgoTestsParameterized, JoinFieldsAlgo_Parameterized)
{
  //boundary_.reset();
  //ASSERT_TRUE(algo_.runImpl(latVol1_));
  //ASSERT_THAT(boundary_, NotNull());
  //EXPECT_TRUE(boundary_->vmesh()->is_quadsurfmesh());
}

INSTANTIATE_TEST_CASE_P(
  JoinFieldsAlgo_Parameterized,
  JoinFieldsAlgoTestsParameterized,
  Combine(Bool(), Bool(), Bool(), Bool(), Bool(), Values(1e-1,1e-3))
  );

#else
TEST(DummyTest, CombineIsNotSupportedOnThisPlatform){}
//
#endif

#endif
<commit_msg>Initial JoinField_parameter testing. Several fails<commit_after>/*
   For more information, please see: http://software.sci.utah.edu

   The MIT License

   Copyright (c) 2012 Scientific Computing and Imaging Institute,
   University of Utah.

   License for the specific language governing rights and limitations under
   Permission is hereby granted, free of charge, to any person obtaining a
   copy of this software and associated documentation files (the "Software"),
   to deal in the Software without restriction, including without limitation
   the rights to use, copy, modify, merge, publish, distribute, sublicense,
   and/or sell copies of the Software, and to permit persons to whom the
   Software is furnished to do so, subject to the following conditions:

   The above copyright notice and this permission notice shall be included
   in all copies or substantial portions of the Software.

   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
   OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
   FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
   THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
   LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
   FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
   DEALINGS IN THE SOFTWARE.
*/

#include <gtest/gtest.h>
#include <gmock/gmock.h>

#include <Core/Datatypes/Legacy/Field/VField.h>
#include <Core/Datatypes/Legacy/Field/FieldInformation.h>
#include <Core/Datatypes/Matrix.h>
#include <Core/Algorithms/Base/AlgorithmPreconditions.h>
#include <Core/Algorithms/Legacy/Fields/MergeFields/JoinFieldsAlgo.h>
#include <Core/Algorithms/Base/AlgorithmVariableNames.h>
#include <Testing/Utils/SCIRunUnitTests.h>
#include <Testing/Utils/MatrixTestUtilities.h>
#include <Core/Logging/Log.h>

using namespace SCIRun;
using namespace SCIRun::Core::Datatypes;
using namespace SCIRun::Core::Geometry;
using namespace SCIRun::Core::Algorithms::Fields;
using namespace SCIRun::TestUtils;
using ::testing::NotNull;
using ::testing::TestWithParam;
using ::testing::Values;

class JoinFieldsAlgoTests : public ::testing::Test
{
protected:
  virtual void SetUp()
  {
    SCIRun::Core::Logging::Log::get().setVerbose(true);
  }

  FieldHandle CreateEmptyLatVol(size_type sizex = 3, size_type sizey = 4, size_type sizez = 5)
  {
    FieldInformation lfi("LatVolMesh", 1, "double");
    Point minb(-1.0, -1.0, -1.0);
    Point maxb(1.0, 1.0, 1.0);
    MeshHandle mesh = CreateMesh(lfi, sizex, sizey, sizez, minb, maxb);
    FieldHandle ofh = CreateField(lfi,mesh);
    ofh->vfield()->clear_all_values();
    return ofh;
  }
};

// parameters:
// MergeNodes = Bool()
// MergeElems = Bool()
// MatchNodeValues = Bool()
// MakeNoData = Bool()
// Tolerance = Values(1e-1, 1e-3, ...)

TEST_F(JoinFieldsAlgoTests, CanLogErrorMessage)
{
  JoinFieldsAlgo algo;
  FieldList input;
  FieldHandle output;
  EXPECT_FALSE(algo.runImpl(input, output));
}

TEST_F(JoinFieldsAlgoTests, CanJoinMultipleLatVols)
{
  JoinFieldsAlgo algo;

  FieldList input;
  input.push_back(CreateEmptyLatVol(2,3,4));
  EXPECT_EQ(2*3*4, input[0]->vmesh()->num_nodes());
  input.push_back(CreateEmptyLatVol(5,6,7));
  EXPECT_EQ(5*6*7, input[1]->vmesh()->num_nodes());
  input.push_back(CreateEmptyLatVol(8,9,10));
  EXPECT_EQ(8*9*10, input[2]->vmesh()->num_nodes());

  FieldHandle output;
  EXPECT_TRUE(algo.runImpl(input, output));
  EXPECT_EQ(914, output->vmesh()->num_nodes());

  input.push_back(CreateEmptyLatVol(11,12,13));
  EXPECT_EQ(11*12*13, input[3]->vmesh()->num_nodes());
  EXPECT_TRUE(algo.runImpl(input, output));
  EXPECT_EQ(2588, output->vmesh()->num_nodes());
}

TEST_F(JoinFieldsAlgoTests, CanJoinMultipleLatVolsGeneric)
{
  JoinFieldsAlgo algo;

  FieldList input;
  input.push_back(CreateEmptyLatVol(2,3,4));
  input.push_back(CreateEmptyLatVol(5,6,7));
  input.push_back(CreateEmptyLatVol(8,9,10));

  auto outputObj = algo.run_generic(make_input((JoinFieldsAlgo::InputFields, input)));

  FieldHandle output = outputObj.get<Field>(Core::Algorithms::Variables::OutputField);
  EXPECT_EQ(914, output->vmesh()->num_nodes());
}

//#if SCIRUN4_CODE_TO_BE_ENABLED_LATER

#if GTEST_HAS_COMBINE

/*Get Parameterized Tests*/

using ::testing::Bool;
using ::testing::Values;
using ::testing::Combine;

class JoinFieldsAlgoTestsParameterized : public ::testing::TestWithParam < ::std::tr1::tuple<bool, bool, bool, bool, double> >
{
public:
JoinFieldsAlgo algo_;
FieldList input;
FieldHandle output;
protected:
  virtual void SetUp()
  {
    SCIRun::Core::Logging::Log::get().setVerbose(true);
	// How to set parameters on an algorithm (that come from the GUI)
    algo_.set(JoinFieldsAlgo::MergeNodes,      ::std::tr1::get<0>(GetParam()));
	algo_.set(JoinFieldsAlgo::MergeElems,      ::std::tr1::get<1>(GetParam()));
    algo_.set(JoinFieldsAlgo::MatchNodeValues, ::std::tr1::get<2>(GetParam()));
    algo_.set(JoinFieldsAlgo::MakeNoData,      ::std::tr1::get<3>(GetParam()));
    algo_.set(JoinFieldsAlgo::Tolerance,       ::std::tr1::get<4>(GetParam()));
  }

  FieldHandle CreateEmptyLatVol(size_type sizex = 3, size_type sizey = 4, size_type sizez = 5)
  {
    FieldInformation lfi("LatVolMesh", 1, "double");
    Point minb(-1.0, -1.0, -1.0);
    Point maxb(1.0, 1.0, 1.0);
    MeshHandle mesh = CreateMesh(lfi, sizex, sizey, sizez, minb, maxb);
    FieldHandle ofh = CreateField(lfi,mesh);
    ofh->vfield()->clear_all_values();
    return ofh;
  }
  virtual void TearDown(){}
};

TEST_P(JoinFieldsAlgoTestsParameterized, JoinFieldsAlgo_Parameterized)
{
	input.push_back(CreateEmptyLatVol(2,3,4));
	input.push_back(CreateEmptyLatVol(5,6,7));
	input.push_back(CreateEmptyLatVol(8,9,10));

	algo_.runImpl(input, output);

	EXPECT_EQ(output->vmesh()->num_nodes(), output->vmesh()->num_nodes());

}

TEST_P(JoinFieldsAlgoTestsParameterized, JoinFieldsAlgo_Parameterized_generic)
{
	input.push_back(CreateEmptyLatVol(2,3,4));
	input.push_back(CreateEmptyLatVol(5,6,7));
	input.push_back(CreateEmptyLatVol(8,9,10));

	auto outputObj = algo_.run_generic(make_input((JoinFieldsAlgo::InputFields, input)));
	FieldHandle output = outputObj.get<Field>(Core::Algorithms::Variables::OutputField);
	EXPECT_EQ(output->vmesh()->num_nodes(), output->vmesh()->num_nodes());
}

INSTANTIATE_TEST_CASE_P(
  JoinFieldsAlgo_Parameterized,
  JoinFieldsAlgoTestsParameterized,
  Combine(Bool(), Bool(), Bool(), Bool(), Values(1e-1,1e-3))
  );

#else
TEST(DummyTest, CombineIsNotSupportedOnThisPlatform){}

#endif

//#endif<|endoftext|>


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

#include <string>
#include <vector>
#include <iostream>
#include <fstream>
#include <memory>
#include <cstdlib>

#include "cpp_utils/string.hpp"

namespace dllp {

struct layer {
    virtual void print(std::ostream& out) = 0;
};

struct rbm_layer : layer {
    std::size_t visible = 0;
    std::size_t hidden = 0;

    void print(std::ostream& out) override {
        out << "dll::rbm_layer<>::rbm_t";
    }
};

struct datasource {
    std::string source_file;
    std::string reader;
};

struct task {
    datasource pretraining;
    datasource samples;
    datasource labels;

    std::vector<std::shared_ptr<layer>> layers;
};

void print_usage(){
    std::cout << "Usage: dllp conf_file action" << std::endl;
}

bool starts_with(const std::string& str, const std::string& search){
    return std::mismatch(search.begin(), search.end(), str.begin()).first == search.end();
}

std::string extract_value(const std::string& str, const std::string& search){
    return {str.begin() + str.find(search) + search.size(), str.end()};
}

datasource parse_datasource(const std::vector<std::string>& lines, std::size_t& i){
    datasource source;

    source.reader = "default";

    while(i < lines.size()){
        if(starts_with(lines[i], "source: ")){
            source.source_file = extract_value(lines[i], "source: ");
            ++i;
        } else if(starts_with(lines[i], "reader: ")){
            source.reader = extract_value(lines[i], "reader: ");
            ++i;
        } else {
            break;
        }
    }

    if(source.source_file.empty()){
        std::cout << "dllp:: error: missing source" << std::endl;
    }

    return source;
}

void generate(task& t);
void compile(const char* cxx, const char* ld);

} //end of dllp namespace

int main(int argc, char* argv[]){
    if(argc < 3){
        std::cout << "dllp: Not enough arguments" << std::endl;
        dllp::print_usage();
        return 1;
    }

    const auto* cxx = std::getenv("CXX");
    const auto* ld = std::getenv("LD");

    if(!cxx){
        std::cout << "CXX environment variable must be set" << std::endl;
        return 2;
    }

    if(!ld){
        std::cout << "LD environment variable must be set" << std::endl;
        return 2;
    }

    std::string source_file(argv[1]);
    std::string action(argv[2]);

    std::ifstream source_stream(source_file);

    std::string current_line;
    std::vector<std::string> lines;

    while(std::getline(source_stream, current_line)) {
        lines.push_back(cpp::trim(current_line));
    }

    dllp::task t;

    for(std::size_t i = 0; i < lines.size();){
        auto& current_line = lines[i];

        if(current_line == "input:"){
            ++i;

            if(i == lines.size()){
                std::cout << "dllp: error: input expect at least one child" << std::endl;

                return 1;
            }

            while(i < lines.size()){
                if(lines[i] == "pretraining:"){
                    t.pretraining = dllp::parse_datasource(lines, ++i);
                } else if(lines[i] == "samples:"){
                    t.samples = dllp::parse_datasource(lines, ++i);
                } else if(lines[i] == "labels:"){
                    t.labels = dllp::parse_datasource(lines, ++i);
                } else {
                    break;
                }
            }
        } else if(current_line == "rbm:"){
            ++i;

            if(i == lines.size()){
                std::cout << "dllp: error: rbm expect at least visible and hidden parameters" << std::endl;

                return 1;
            }

            auto rbm = std::make_shared<dllp::rbm_layer>();

            while(i < lines.size()){
                if(dllp::starts_with(lines[i], "visible:")){
                    rbm->visible = std::stol(dllp::extract_value(lines[i], "visible: "));
                    ++i;
                } else if(dllp::starts_with(lines[i], "hidden:")){
                    rbm->hidden = std::stol(dllp::extract_value(lines[i], "hidden: "));
                    ++i;
                } else {
                    break;
                }
            }

            t.layers.push_back(std::move(rbm));
        } else {
            std::cout << "dllp: error: Invalid line: " << current_line << std::endl;

            return 1;
        }
    }

    dllp::generate(t);

    dllp::compile(cxx, ld);

    return 0;
}

namespace dllp {

void generate(task& t){
    std::ofstream out_stream(".dbn.cpp");

    out_stream << "#include <memory>\n";
    out_stream << "#include \"dll/processor/processor.hpp\"\n\n";

    out_stream << "using dbn_t = dll:dbn_desc<dll::dbn_layers<\n";

    //TODO

    std::string comma = "  ";

    for(auto& layer : t.layers){
        out_stream << comma;
        layer->print(out_stream);
        comma = "\n, ";
    }

    out_stream << "\n>>::dbn_t;\n\n";

    out_stream << "int main(int argc, char* argv[]){\n";
    out_stream << "   auto dbn = std::make_unique<dbn_t>();\n";
    out_stream << "}\n";
}

void compile(const char* cxx, const char* ld){
    //TODO
}

} //end of namespace dllp

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

#include <string>
#include <vector>
#include <iostream>
#include <fstream>
#include <memory>
#include <cstdlib>

#include "cpp_utils/string.hpp"

namespace dllp {

struct layer {
    virtual void print(std::ostream& out) = 0;
};

struct rbm_layer : layer {
    std::size_t visible = 0;
    std::size_t hidden = 0;

    void print(std::ostream& out) override {
        out << "dll::rbm_layer<>::rbm_t";
    }
};

struct datasource {
    std::string source_file;
    std::string reader;
};

struct task {
    datasource pretraining;
    datasource samples;
    datasource labels;

    std::vector<std::shared_ptr<layer>> layers;
};

void print_usage(){
    std::cout << "Usage: dllp conf_file action" << std::endl;
}

bool starts_with(const std::string& str, const std::string& search){
    return std::mismatch(search.begin(), search.end(), str.begin()).first == search.end();
}

std::string extract_value(const std::string& str, const std::string& search){
    return {str.begin() + str.find(search) + search.size(), str.end()};
}

datasource parse_datasource(const std::vector<std::string>& lines, std::size_t& i){
    datasource source;

    source.reader = "default";

    while(i < lines.size()){
        if(starts_with(lines[i], "source: ")){
            source.source_file = extract_value(lines[i], "source: ");
            ++i;
        } else if(starts_with(lines[i], "reader: ")){
            source.reader = extract_value(lines[i], "reader: ");
            ++i;
        } else {
            break;
        }
    }

    if(source.source_file.empty()){
        std::cout << "dllp:: error: missing source" << std::endl;
    }

    return source;
}

void generate(task& t);
void compile(const char* cxx);

} //end of dllp namespace

int main(int argc, char* argv[]){
    if(argc < 3){
        std::cout << "dllp: Not enough arguments" << std::endl;
        dllp::print_usage();
        return 1;
    }

    const auto* cxx = std::getenv("CXX");

    if(!cxx){
        std::cout << "CXX environment variable must be set" << std::endl;
        return 2;
    }

    std::string source_file(argv[1]);
    std::string action(argv[2]);

    std::ifstream source_stream(source_file);

    std::string current_line;
    std::vector<std::string> lines;

    while(std::getline(source_stream, current_line)) {
        lines.push_back(cpp::trim(current_line));
    }

    dllp::task t;

    for(std::size_t i = 0; i < lines.size();){
        auto& current_line = lines[i];

        if(current_line == "input:"){
            ++i;

            if(i == lines.size()){
                std::cout << "dllp: error: input expect at least one child" << std::endl;

                return 1;
            }

            while(i < lines.size()){
                if(lines[i] == "pretraining:"){
                    t.pretraining = dllp::parse_datasource(lines, ++i);
                } else if(lines[i] == "samples:"){
                    t.samples = dllp::parse_datasource(lines, ++i);
                } else if(lines[i] == "labels:"){
                    t.labels = dllp::parse_datasource(lines, ++i);
                } else {
                    break;
                }
            }
        } else if(current_line == "rbm:"){
            ++i;

            if(i == lines.size()){
                std::cout << "dllp: error: rbm expect at least visible and hidden parameters" << std::endl;

                return 1;
            }

            auto rbm = std::make_shared<dllp::rbm_layer>();

            while(i < lines.size()){
                if(dllp::starts_with(lines[i], "visible:")){
                    rbm->visible = std::stol(dllp::extract_value(lines[i], "visible: "));
                    ++i;
                } else if(dllp::starts_with(lines[i], "hidden:")){
                    rbm->hidden = std::stol(dllp::extract_value(lines[i], "hidden: "));
                    ++i;
                } else {
                    break;
                }
            }

            t.layers.push_back(std::move(rbm));
        } else {
            std::cout << "dllp: error: Invalid line: " << current_line << std::endl;

            return 1;
        }
    }

    dllp::generate(t);

    dllp::compile(cxx);

    return 0;
}

namespace dllp {

void generate(task& t){
    std::ofstream out_stream(".dbn.cpp");

    out_stream << "#include <memory>\n";
    out_stream << "#include \"dll/processor/processor.hpp\"\n\n";

    out_stream << "using dbn_t = dll:dbn_desc<dll::dbn_layers<\n";

    //TODO

    std::string comma = "  ";

    for(auto& layer : t.layers){
        out_stream << comma;
        layer->print(out_stream);
        comma = "\n, ";
    }

    out_stream << "\n>>::dbn_t;\n\n";

    out_stream << "int main(int argc, char* argv[]){\n";
    out_stream << "   auto dbn = std::make_unique<dbn_t>();\n";
    out_stream << "}\n";
}

void compile(const char* cxx){
    std::string compile_command(cxx);

    compile_command += " -o .dbn.out ";
    compile_command += " -I/usr/include/dll/ ";
    compile_command += " .dbn.cpp ";

    int compile_result = system(compile_command.c_str());

    if(compile_result){
        std::cout << "Compilation failed" << std::endl;
    }
}

} //end of namespace dllp

<|endoftext|>


<commit_before>//
//  TextureBuilder.hpp
//  Clock Signal
//
//  Created by Thomas Harte on 08/03/2016.
//  Copyright © 2016 Thomas Harte. All rights reserved.
//

#ifndef Outputs_CRT_Internals_TextureBuilder_hpp
#define Outputs_CRT_Internals_TextureBuilder_hpp

#include <cstdint>
#include <functional>
#include <memory>
#include <vector>

#include "OpenGL.hpp"
#include "CRTConstants.hpp"

namespace Outputs {
namespace CRT {

/*!
	Owns an OpenGL texture resource and provides mechanisms to fill it from bottom left to top right
	with runs of data, ensuring each run is neighboured immediately to the left and right by copies of its
	first and last pixels.

	Although this class is not itself inherently thread safe, it is built to permit one serialised stream
	of calls to provide source data, with an interceding (but also serialised) submission to the GPU at any time.

	Intended usage by the data generator:

		(i)		allocate a write area with allocate_write_area, supplying a maximum size.
		(ii)	call reduce_previous_allocation_to to announce the actual size written.

	This will cause you to have added source data to the target texture. You can then either use that data
	or allow it to expire.

		(iii)	call retain_latest to add the most recently written write area to the flush queue.

	The flush queue contains provisional data, that can sit in the CPU's memory space indefinitely. This facility
	is provided because it is expected that a texture will be built alontside some other collection of data —
	that data in the flush queue is expected to become useful in coordination with something else but should
	be retained at least until then.

		(iv)	call flush to move data to the submit queue.

	When you flush, you'll receive a record of the bounds of all newly-flushed areas of source data. That gives
	an opportunity to correlate the data with whatever else it is being tied to. It will continue to sit in
	the CPU's memory space but has now passed beyond any further modification or reporting.

	Intended usage by the GPU owner:

		(i)		call submit to move data to the GPU and free up its CPU-side resources.

	The latest data is now on the GPU, regardless of where the data provider may be in its process — only data
	that has entered the submission queue is uploaded.

*/
class TextureBuilder {
	public:
		/// Constructs an instance of InputTextureBuilder that contains a texture of colour depth @c bytes_per_pixel;
		/// this creates a new texture and binds it to the current active texture unit.
		TextureBuilder(size_t bytes_per_pixel, GLenum texture_unit);
		virtual ~TextureBuilder();

		/// Finds the first available space of at least @c required_length pixels in size which is suitably aligned
		/// for writing of @c required_alignment number of pixels at a time.
		/// Calls must be paired off with calls to @c reduce_previous_allocation_to.
		/// @returns a pointer to the allocated space if any was available; @c nullptr otherwise.
		uint8_t *allocate_write_area(size_t required_length, size_t required_alignment = 1);

		/// Announces that the owner is finished with the region created by the most recent @c allocate_write_area
		/// and indicates that its actual final size was @c actual_length.
		void reduce_previous_allocation_to(size_t actual_length);

		/// Allocated runs are provisional; they will not appear in the next flush queue unless retained.
		/// @returns @c true if a retain succeeded; @c false otherwise.
		bool retain_latest();

		// Undoes the most recent retain_latest. Undefined behaviour if a submission has occurred in the interim.
		void discard_latest();

		/// @returns @c true if all future calls to @c allocate_write_area will fail on account of the input texture
		/// being full; @c false if calls may succeed.
		bool is_full();

		/// Updates the currently-bound texture with all new data provided since the last @c submit.
		void submit();

		struct WriteArea {
			uint16_t x, y, length;
		};
		/// Finalises all write areas allocated since the last call to @c flush. Only finalised areas will be
		/// submitted upon the next @c submit. The supplied function will be called with a list of write areas
		/// allocated, indicating their final resting locations and their lengths.
		void flush(const std::function<void(const std::vector<WriteArea> &write_areas, size_t count)> &);

	private:
		// the buffer size
		size_t bytes_per_pixel_;

		// the buffer
		std::vector<uint8_t> image_;
		GLuint texture_name_;

		// the current write area
		WriteArea write_area_;

		// the list of write areas that have ascended to the flush queue
		std::vector<WriteArea> write_areas_;
		size_t number_of_write_areas_;
		bool is_full_, was_full_;
		uint16_t first_unsubmitted_y_;
		inline uint8_t *pointer_to_location(uint16_t x, uint16_t y);

		// Usually: the start position for the current batch of write areas.
		// Caveat: reset to the origin upon a submit. So used in comparison by flush to
		// determine whether the current batch of write areas needs to be relocated.
		uint16_t write_areas_start_x_, write_areas_start_y_;
};

}
}

#endif /* Outputs_CRT_Internals_TextureBuilder_hpp */
<commit_msg>Sketches interface for a GPU data bookender, to avoid stray errors with packed pixel formats.<commit_after>//
//  TextureBuilder.hpp
//  Clock Signal
//
//  Created by Thomas Harte on 08/03/2016.
//  Copyright © 2016 Thomas Harte. All rights reserved.
//

#ifndef Outputs_CRT_Internals_TextureBuilder_hpp
#define Outputs_CRT_Internals_TextureBuilder_hpp

#include <cstdint>
#include <functional>
#include <memory>
#include <vector>

#include "OpenGL.hpp"
#include "CRTConstants.hpp"

namespace Outputs {
namespace CRT {

/*!
	Owns an OpenGL texture resource and provides mechanisms to fill it from bottom left to top right
	with runs of data, ensuring each run is neighboured immediately to the left and right by copies of its
	first and last pixels.

	Although this class is not itself inherently thread safe, it is built to permit one serialised stream
	of calls to provide source data, with an interceding (but also serialised) submission to the GPU at any time.

	Intended usage by the data generator:

		(i)		allocate a write area with allocate_write_area, supplying a maximum size.
		(ii)	call reduce_previous_allocation_to to announce the actual size written.

	This will cause you to have added source data to the target texture. You can then either use that data
	or allow it to expire.

		(iii)	call retain_latest to add the most recently written write area to the flush queue.

	The flush queue contains provisional data, that can sit in the CPU's memory space indefinitely. This facility
	is provided because it is expected that a texture will be built alontside some other collection of data —
	that data in the flush queue is expected to become useful in coordination with something else but should
	be retained at least until then.

		(iv)	call flush to move data to the submit queue.

	When you flush, you'll receive a record of the bounds of all newly-flushed areas of source data. That gives
	an opportunity to correlate the data with whatever else it is being tied to. It will continue to sit in
	the CPU's memory space but has now passed beyond any further modification or reporting.

	Intended usage by the GPU owner:

		(i)		call submit to move data to the GPU and free up its CPU-side resources.

	The latest data is now on the GPU, regardless of where the data provider may be in its process — only data
	that has entered the submission queue is uploaded.

*/
class TextureBuilder {
	public:
		/// Constructs an instance of InputTextureBuilder that contains a texture of colour depth @c bytes_per_pixel;
		/// this creates a new texture and binds it to the current active texture unit.
		TextureBuilder(size_t bytes_per_pixel, GLenum texture_unit);
		virtual ~TextureBuilder();

		/// Finds the first available space of at least @c required_length pixels in size which is suitably aligned
		/// for writing of @c required_alignment number of pixels at a time.
		/// Calls must be paired off with calls to @c reduce_previous_allocation_to.
		/// @returns a pointer to the allocated space if any was available; @c nullptr otherwise.
		uint8_t *allocate_write_area(size_t required_length, size_t required_alignment = 1);

		/// Announces that the owner is finished with the region created by the most recent @c allocate_write_area
		/// and indicates that its actual final size was @c actual_length.
		void reduce_previous_allocation_to(size_t actual_length);

		/// Allocated runs are provisional; they will not appear in the next flush queue unless retained.
		/// @returns @c true if a retain succeeded; @c false otherwise.
		bool retain_latest();

		// Undoes the most recent retain_latest. Undefined behaviour if a submission has occurred in the interim.
		void discard_latest();

		/// @returns @c true if all future calls to @c allocate_write_area will fail on account of the input texture
		/// being full; @c false if calls may succeed.
		bool is_full();

		/// Updates the currently-bound texture with all new data provided since the last @c submit.
		void submit();

		struct WriteArea {
			uint16_t x, y, length;
		};
		/// Finalises all write areas allocated since the last call to @c flush. Only finalised areas will be
		/// submitted upon the next @c submit. The supplied function will be called with a list of write areas
		/// allocated, indicating their final resting locations and their lengths.
		void flush(const std::function<void(const std::vector<WriteArea> &write_areas, size_t count)> &);

		/// A Bookender helps to paper over precision errors when rendering; its job is to provide single-sample
		/// extensions that duplicate the left and right edges of a written area. By default the texture builder will
		/// simply copy the appropriate number of bytes per pixel, but if the client is using a packed pixel format
		/// then that may be incorrect, e.g. if each sample is a byte but contains two pixels, each in a single nibble,
		/// then the correct duplication might be a byte composed of copies of the two top nibbles as the left bookend,
		/// and one composed of copies of the two bottom nibbles on the right.
		struct Bookender {
			/// Writes to left_bookend the sample that should appear as a continuation before the left_value;
			/// writes to right_bookend the sample that should appear as a continuation after right_value.
			void add_bookends(uint8_t *const left_value, uint8_t *const right_value, uint8_t *left_bookend, uint8_t *right_bookend);
		};

		/// Sets the current bookender. Will be called synchronously within the builder-writing thread.
		void set_bookender(Bookender *bookender);

	private:
		// the buffer size
		size_t bytes_per_pixel_;

		// the buffer
		std::vector<uint8_t> image_;
		GLuint texture_name_;

		// the current write area
		WriteArea write_area_;

		// the list of write areas that have ascended to the flush queue
		std::vector<WriteArea> write_areas_;
		size_t number_of_write_areas_;
		bool is_full_, was_full_;
		uint16_t first_unsubmitted_y_;
		inline uint8_t *pointer_to_location(uint16_t x, uint16_t y);

		// Usually: the start position for the current batch of write areas.
		// Caveat: reset to the origin upon a submit. So used in comparison by flush to
		// determine whether the current batch of write areas needs to be relocated.
		uint16_t write_areas_start_x_, write_areas_start_y_;
};

}
}

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


<commit_before>#pragma once
/*
**  Copyright (C) 2012 Aldebaran Robotics
**  See COPYING for the license
*/

#ifndef _SRC_TRANSPORTSOCKET_HPP_
#define _SRC_TRANSPORTSOCKET_HPP_

# include <boost/noncopyable.hpp>
# include <boost/variant.hpp>
# include <qi/future.hpp>
# include "message.hpp"
# include <qi/url.hpp>
# include <qi/eventloop.hpp>
# include <qi/signal.hpp>
# include <qi/binarycodec.hpp>
# include <string>
# include "messagedispatcher.hpp"
# include "streamcontext.hpp"

namespace qi {
  namespace detail {
    template<>
    struct HasLess<boost::variant<std::string, qi::Message> >{
      static const bool value = false;
    };
  }
}

QI_TYPE_CONCRETE(boost::variant<std::string QI_COMMA qi::Message>);

namespace qi
{
  class Session;

  class TransportSocket : private boost::noncopyable, public StreamContext
  {
  public:
    virtual ~TransportSocket();
    enum Status {
      Status_Disconnected  = 0,
      Status_Connecting    = 1,
      Status_Connected     = 2,
      Status_Disconnecting = 3,
    };
    enum Event {
      Event_Error = 0,
      Event_Message = 1,
    };

    explicit TransportSocket(qi::EventLoop* eventLoop = qi::getEventLoop())
      : _eventLoop(NULL)
      , _err(0)
      , _status(Status_Disconnected)
    {
      connected.setCallType(MetaCallType_Queued);
      disconnected.setCallType(MetaCallType_Queued);
      // Set messageReady signal to async mode to protect our network thread
      messageReady.setCallType(MetaCallType_Queued);
      socketEvent.setCallType(MetaCallType_Queued);
    }

    virtual qi::FutureSync<void> connect(const qi::Url &url) = 0;
    virtual qi::FutureSync<void> disconnect()                = 0;

    virtual bool send(const qi::Message &msg)                = 0;
    /// Must be called once if the socket is obtained through TransportServer::newConnection()
    virtual void  startReading() = 0;

    virtual qi::Url remoteEndpoint() const = 0;

    qi::Url url() const {
      return _url;
    }

    Status status() const {
      return _status;
    }

    int error() const
    {
      return _err;
    }

    bool isConnected() const
    {
      return _status == qi::TransportSocket::Status_Connected;
    }

    static const unsigned int ALL_OBJECTS = (unsigned int)-1;

    qi::SignalLink messagePendingConnect(unsigned int serviceId, unsigned int objectId, boost::function<void (const qi::Message&)> fun) {
      return _dispatcher.messagePendingConnect(serviceId, objectId, fun);
    }

    bool                 messagePendingDisconnect(unsigned int serviceId, unsigned int objectId, qi::SignalLink linkId) {
      return _dispatcher.messagePendingDisconnect(serviceId, objectId, linkId);
    }

  protected:
    qi::EventLoop*          _eventLoop;
    qi::MessageDispatcher   _dispatcher;

    int                     _err;
    TransportSocket::Status _status;
    qi::Url                 _url;

  public:
    // C4251
    qi::Signal<>                   connected;
    // C4251
    qi::Signal<std::string>        disconnected;
    // C4251
    qi::Signal<const qi::Message&> messageReady;
    typedef boost::variant<std::string, qi::Message> SocketEventData;
    // C4251
    qi::Signal<SocketEventData>  socketEvent;
  };

  typedef boost::shared_ptr<TransportSocket> TransportSocketPtr;

  TransportSocketPtr makeTransportSocket(const std::string &protocol, qi::EventLoop *eventLoop = getEventLoop());

}

#endif  // _SRC_TRANSPORTSOCKET_HPP_
<commit_msg>TransportSocket: use synchronous signals #32213<commit_after>#pragma once
/*
**  Copyright (C) 2012 Aldebaran Robotics
**  See COPYING for the license
*/

#ifndef _SRC_TRANSPORTSOCKET_HPP_
#define _SRC_TRANSPORTSOCKET_HPP_

# include <boost/noncopyable.hpp>
# include <boost/variant.hpp>
# include <qi/future.hpp>
# include "message.hpp"
# include <qi/url.hpp>
# include <qi/eventloop.hpp>
# include <qi/signal.hpp>
# include <qi/binarycodec.hpp>
# include <string>
# include "messagedispatcher.hpp"
# include "streamcontext.hpp"

namespace qi {
  namespace detail {
    template<>
    struct HasLess<boost::variant<std::string, qi::Message> >{
      static const bool value = false;
    };
  }
}

QI_TYPE_CONCRETE(boost::variant<std::string QI_COMMA qi::Message>);

namespace qi
{
  class Session;

  class TransportSocket : private boost::noncopyable, public StreamContext
  {
  public:
    virtual ~TransportSocket();
    enum Status {
      Status_Disconnected  = 0,
      Status_Connecting    = 1,
      Status_Connected     = 2,
      Status_Disconnecting = 3,
    };
    enum Event {
      Event_Error = 0,
      Event_Message = 1,
    };

    explicit TransportSocket(qi::EventLoop* eventLoop = qi::getEventLoop())
      : _eventLoop(NULL)
      , _err(0)
      , _status(Status_Disconnected)
    {
      // TODO: these two should be direct too
      connected.setCallType(MetaCallType_Queued);
      disconnected.setCallType(MetaCallType_Queued);
      messageReady.setCallType(MetaCallType_Direct);
      socketEvent.setCallType(MetaCallType_Direct);
    }

    virtual qi::FutureSync<void> connect(const qi::Url &url) = 0;
    virtual qi::FutureSync<void> disconnect()                = 0;

    virtual bool send(const qi::Message &msg)                = 0;
    /// Must be called once if the socket is obtained through TransportServer::newConnection()
    virtual void  startReading() = 0;

    virtual qi::Url remoteEndpoint() const = 0;

    qi::Url url() const {
      return _url;
    }

    Status status() const {
      return _status;
    }

    int error() const
    {
      return _err;
    }

    bool isConnected() const
    {
      return _status == qi::TransportSocket::Status_Connected;
    }

    static const unsigned int ALL_OBJECTS = (unsigned int)-1;

    qi::SignalLink messagePendingConnect(unsigned int serviceId, unsigned int objectId, boost::function<void (const qi::Message&)> fun) {
      return _dispatcher.messagePendingConnect(serviceId, objectId, fun);
    }

    bool                 messagePendingDisconnect(unsigned int serviceId, unsigned int objectId, qi::SignalLink linkId) {
      return _dispatcher.messagePendingDisconnect(serviceId, objectId, linkId);
    }

  protected:
    qi::EventLoop*          _eventLoop;
    qi::MessageDispatcher   _dispatcher;

    int                     _err;
    TransportSocket::Status _status;
    qi::Url                 _url;

  public:
    // C4251
    qi::Signal<>                   connected;
    // C4251
    qi::Signal<std::string>        disconnected;
    // C4251
    qi::Signal<const qi::Message&> messageReady;
    typedef boost::variant<std::string, qi::Message> SocketEventData;
    // C4251
    qi::Signal<SocketEventData>  socketEvent;
  };

  typedef boost::shared_ptr<TransportSocket> TransportSocketPtr;

  TransportSocketPtr makeTransportSocket(const std::string &protocol, qi::EventLoop *eventLoop = getEventLoop());

}

#endif  // _SRC_TRANSPORTSOCKET_HPP_
<|endoftext|>


<commit_before>#pragma once

#include <boost/variant/variant.hpp>
#include "../frontend/Logic.hpp"
#include "../frontend/QF_BV.hpp"
#include "Types.hpp"

namespace metaSMT {

  namespace type {

    /**
     * \brief symbols with type information
     *
     * TypedSymbols annotate metaSMT's primitive symbols (predicate,
     * bitvector, and Context::result_type) with additional type
     * information (Boolean or BitVector).
     *
     * The type information is especially useful when expressions
     * become evaluated and stored as Context::result_types.
     * Additionally, TypedSymbols allow for easy conversion from one
     * type to another, e.g., predicate to bitvector.
     *
     * *Warning*: The Context in TypedSymbol<Context> and
     * Context::result_type must never change!
     *
     * \code
     *  // create typed symbol from predicate
     *  TypedSymbol<ContextType> p(new_variable());
     *
     *  // create typed symbol from bitvector primitive
     *  unsigned char const w = 32;
     *  TypedSymbol<ContextType> bv(new_bitvector(w), w);
     *
     *  // create typed symbol from Context::result_type
     *  typename Context::result_type r = bv.eval(ctx);
     *  TypedSymbol<Context> expr(r, type::BitVector(w));
     *
     * \endcode
     * \ingroup type
     * \defgroup TypedSymbol TypedSymbol
     * @{
     */

    namespace bv = logic::QF_BV;

    /* Forward TypedSymbol*/
    template < typename Context >
    struct TypedSymbol;

    /** \cond **/
    namespace detail {

      template < typename Context >
      struct Expr {
        typedef boost::variant<
          logic::predicate
          , bv::bitvector
          , typename Context::result_type
          > type;
      }; /* Expr */

      template < typename Context >
      class convert_to_result_type_visitor
        : public boost::static_visitor<typename Context::result_type> {
      public:
        convert_to_result_type_visitor(Context &ctx)
          : ctx_(ctx)
        {}

        typename Context::result_type
        operator()(logic::predicate const &expr) const {
          return evaluate(ctx_, expr);
        }

        typename Context::result_type
        operator()(bv::bitvector const &expr) const {
          return evaluate(ctx_, expr);
        }

        typename Context::result_type
        operator()(typename Context::result_type const &expr) const {
          return expr;
        }

        Context &ctx_;
      }; /* convert_to_result_type_visitor */

      /**
       * \brief Evaluates an Expr and returns Context::result_type
       * \param expr The expression
       * \param ctx The metaSMT Context
       * \return the evaluated expression
       *
       */
      template < typename Context >
      typename Context::result_type to_result_type(Context &ctx,
                                                   typename Expr<Context>::type const &expr) {
        return boost::apply_visitor( convert_to_result_type_visitor<Context>(ctx),
                                     expr );
      }

      template < typename Type >
      class is_type_visitor : public boost::static_visitor<bool> {
      public:
        is_type_visitor() {}

        bool operator()(Type const &) const {
          return true;
        }

        template < typename OtherType >
        bool operator()(OtherType const &) const {
          return false;
        }
      }; /* is_value_visitor */

      /**
       * \brief Compare value
       * \param expr The expression
       * \return true iff expr corresponds to Type
       *
       */
      template < typename Context, typename Type >
      bool is_value(typename Expr<Context>::type const &expr) {
        return boost::apply_visitor( is_type_visitor<Type>(), expr );
      }

      /**
       * \brief Compare type
       * \param type The type
       * \return true iff type corresponds to Type
       *
       */
      template < typename Type >
      bool is_type(any_type const &type) {
        return boost::apply_visitor( is_type_visitor<Type>(), type );
      }

      template < typename Context >
      class convert_to_bitvector_visitor
        : public boost::static_visitor<typename Context::result_type> {
      public:
        convert_to_bitvector_visitor(Context &ctx,
                                     TypedSymbol<Context> &typed_symbol)
          : ctx_(ctx)
          , s_(typed_symbol)
        {}

        typename Context::result_type operator()(Boolean const &) const {
          return evaluate(ctx_, logic::Ite(s_.eval(ctx_),
                                    bv::bit1, bv::bit0));
        }

        typename Context::result_type operator()(BitVector const &) const {
          return evaluate(ctx_, s_.eval(ctx_));
        }

        Context &ctx_;
        TypedSymbol<Context> &s_;
      }; // convert_to_bitvector_visitor

      /**
       * \brief Converts a TypedSymbol of Boolean type to BitVector
       * \param ctx The context to work on
       * \param sy The symbol to be converted
       * \return an expression corresponding to the converted bitvector
       *
       */
      template < typename Context >
      typename Context::result_type to_bitvector(Context &ctx,
                                                 TypedSymbol<Context> &sy) {
        return boost::apply_visitor( convert_to_bitvector_visitor<Context>(ctx, sy),
                                     sy.type );
      }

      template < typename Context >
      class convert_to_bool_visitor
        : public boost::static_visitor<typename Context::result_type> {
      public:
        convert_to_bool_visitor(Context &ctx,
                                TypedSymbol<Context> &typed_symbol)
          : ctx_(ctx)
          , s_(typed_symbol)
        {}

        typename Context::result_type operator()(Boolean const &) const {
          return evaluate(ctx_, s_.eval(ctx_));
        }

        typename Context::result_type operator()(BitVector const &bv) const {
          return evaluate(ctx_, logic::nequal(s_.eval(ctx_),
                                              bv::bvuint(0, bv.width)));
        }

        Context &ctx_;
        TypedSymbol<Context> &s_;
      }; // convert_to_bool_visitor

      /**
       * \brief Converts a TypedSymbol of BitVector type to Boolean
       * \param ctx The context to work on
       * \param sy The symbol to be converted
       * \return an expression corresponding to the converted boolean
       *
       */
      template < typename Context >
      typename Context::result_type to_bool(Context &ctx,
                                            TypedSymbol<Context> &sy) {
        return boost::apply_visitor( convert_to_bool_visitor<Context>(ctx, sy),
                                     sy.type );
      }

    } /* detail */
    /** \endcond **/

    template < typename Context >
    struct TypedSymbol {
      typedef typename Context::result_type result_type;

      TypedSymbol(logic::predicate p)
        : value(p)
        , type(Boolean())
      {}

      TypedSymbol(bv::bitvector bv, unsigned const w)
        : value(bv)
        , type(BitVector(w))
      {}

      TypedSymbol(result_type s,
                  any_type ty)
        : value(s)
      , type(ty)
      {}

      TypedSymbol(TypedSymbol<Context> const &other)
        : value(other.value)
        , type(other.type)
      {}

      bool operator==(TypedSymbol<Context> const &other) const {
        return (value == other.value &&
                type == other.type);
      }

      typename Context::result_type eval(Context &ctx) const {
        return detail::to_result_type(ctx, value);
      }

      // value == predicate && type == Boolean
      inline bool isPrimitiveBool() const {
        return detail::is_value<Context, logic::predicate>( value );
      }

      // value == bitvector && type == BitVector
      inline bool isPrimitiveBitVector() const {
        return detail::is_value<Context, bv::bitvector>( value );
      }

      inline bool isPrimitive() const {
        return isPrimitiveBool() || isPrimitiveBitVector();
      }

      inline bool isExpression() const {
        return detail::is_value<Context,typename Context::result_type>( value );
      }

      inline bool isBool() const {
        return detail::is_type<Boolean>( type );
      }

      inline bool isBitVector() const {
        return detail::is_type<BitVector>( type );
      }

      template < typename Type >
      inline Type getType(Type const &) const {
        return boost::get<Type>(type);
      }

      template < typename Type >
      inline Type getType() const {
        return boost::get<Type>(type);
      }

      inline typename Context::result_type toBV(Context &ctx) {
        return detail::to_bitvector(ctx, *this);
      }

      inline typename Context::result_type toBV(Context &ctx,
                                                unsigned const width) {
        if (isBool()) {
          return evaluate(ctx, zero_extend(width-1,
                                           detail::to_bitvector(ctx, *this)));
        } else {
          BitVector bvtype = getType(BitVector());
          assert(width > bvtype.width);
          return evaluate(ctx, zero_extend(width-bvtype.width,
                                           detail::to_bitvector(ctx, *this)));
        }
      }

      inline typename Context::result_type toBool(Context &ctx) {
        return detail::to_bool(ctx, *this);
      }

      typename detail::Expr<Context>::type value;
      any_type type;

    }; /* TypedSymbol */

  } /* type */

  /**@}*/

} /* metaSMT */
<commit_msg>fixed missing namespace in TypedSymbol.hpp<commit_after>#pragma once

#include <boost/variant/variant.hpp>
#include "../frontend/Logic.hpp"
#include "../frontend/QF_BV.hpp"
#include "Types.hpp"

namespace metaSMT {

  namespace type {

    /**
     * \brief symbols with type information
     *
     * TypedSymbols annotate metaSMT's primitive symbols (predicate,
     * bitvector, and Context::result_type) with additional type
     * information (Boolean or BitVector).
     *
     * The type information is especially useful when expressions
     * become evaluated and stored as Context::result_types.
     * Additionally, TypedSymbols allow for easy conversion from one
     * type to another, e.g., predicate to bitvector.
     *
     * *Warning*: The Context in TypedSymbol<Context> and
     * Context::result_type must never change!
     *
     * \code
     *  // create typed symbol from predicate
     *  TypedSymbol<ContextType> p(new_variable());
     *
     *  // create typed symbol from bitvector primitive
     *  unsigned char const w = 32;
     *  TypedSymbol<ContextType> bv(new_bitvector(w), w);
     *
     *  // create typed symbol from Context::result_type
     *  typename Context::result_type r = bv.eval(ctx);
     *  TypedSymbol<Context> expr(r, type::BitVector(w));
     *
     * \endcode
     * \ingroup type
     * \defgroup TypedSymbol TypedSymbol
     * @{
     */

    namespace bv = logic::QF_BV;

    /* Forward TypedSymbol*/
    template < typename Context >
    struct TypedSymbol;

    /** \cond **/
    namespace detail {

      template < typename Context >
      struct Expr {
        typedef boost::variant<
          logic::predicate
          , bv::bitvector
          , typename Context::result_type
          > type;
      }; /* Expr */

      template < typename Context >
      class convert_to_result_type_visitor
        : public boost::static_visitor<typename Context::result_type> {
      public:
        convert_to_result_type_visitor(Context &ctx)
          : ctx_(ctx)
        {}

        typename Context::result_type
        operator()(logic::predicate const &expr) const {
          return evaluate(ctx_, expr);
        }

        typename Context::result_type
        operator()(bv::bitvector const &expr) const {
          return evaluate(ctx_, expr);
        }

        typename Context::result_type
        operator()(typename Context::result_type const &expr) const {
          return expr;
        }

        Context &ctx_;
      }; /* convert_to_result_type_visitor */

      /**
       * \brief Evaluates an Expr and returns Context::result_type
       * \param expr The expression
       * \param ctx The metaSMT Context
       * \return the evaluated expression
       *
       */
      template < typename Context >
      typename Context::result_type to_result_type(Context &ctx,
                                                   typename Expr<Context>::type const &expr) {
        return boost::apply_visitor( convert_to_result_type_visitor<Context>(ctx),
                                     expr );
      }

      template < typename Type >
      class is_type_visitor : public boost::static_visitor<bool> {
      public:
        is_type_visitor() {}

        bool operator()(Type const &) const {
          return true;
        }

        template < typename OtherType >
        bool operator()(OtherType const &) const {
          return false;
        }
      }; /* is_value_visitor */

      /**
       * \brief Compare value
       * \param expr The expression
       * \return true iff expr corresponds to Type
       *
       */
      template < typename Context, typename Type >
      bool is_value(typename Expr<Context>::type const &expr) {
        return boost::apply_visitor( is_type_visitor<Type>(), expr );
      }

      /**
       * \brief Compare type
       * \param type The type
       * \return true iff type corresponds to Type
       *
       */
      template < typename Type >
      bool is_type(any_type const &type) {
        return boost::apply_visitor( is_type_visitor<Type>(), type );
      }

      template < typename Context >
      class convert_to_bitvector_visitor
        : public boost::static_visitor<typename Context::result_type> {
      public:
        convert_to_bitvector_visitor(Context &ctx,
                                     TypedSymbol<Context> &typed_symbol)
          : ctx_(ctx)
          , s_(typed_symbol)
        {}

        typename Context::result_type operator()(Boolean const &) const {
          return evaluate(ctx_, logic::Ite(s_.eval(ctx_),
                                    bv::bit1, bv::bit0));
        }

        typename Context::result_type operator()(BitVector const &) const {
          return evaluate(ctx_, s_.eval(ctx_));
        }

        Context &ctx_;
        TypedSymbol<Context> &s_;
      }; // convert_to_bitvector_visitor

      /**
       * \brief Converts a TypedSymbol of Boolean type to BitVector
       * \param ctx The context to work on
       * \param sy The symbol to be converted
       * \return an expression corresponding to the converted bitvector
       *
       */
      template < typename Context >
      typename Context::result_type to_bitvector(Context &ctx,
                                                 TypedSymbol<Context> &sy) {
        return boost::apply_visitor( convert_to_bitvector_visitor<Context>(ctx, sy),
                                     sy.type );
      }

      template < typename Context >
      class convert_to_bool_visitor
        : public boost::static_visitor<typename Context::result_type> {
      public:
        convert_to_bool_visitor(Context &ctx,
                                TypedSymbol<Context> &typed_symbol)
          : ctx_(ctx)
          , s_(typed_symbol)
        {}

        typename Context::result_type operator()(Boolean const &) const {
          return evaluate(ctx_, s_.eval(ctx_));
        }

        typename Context::result_type operator()(BitVector const &bv) const {
          return evaluate(ctx_, logic::nequal(s_.eval(ctx_),
                                              bv::bvuint(0, bv.width)));
        }

        Context &ctx_;
        TypedSymbol<Context> &s_;
      }; // convert_to_bool_visitor

      /**
       * \brief Converts a TypedSymbol of BitVector type to Boolean
       * \param ctx The context to work on
       * \param sy The symbol to be converted
       * \return an expression corresponding to the converted boolean
       *
       */
      template < typename Context >
      typename Context::result_type to_bool(Context &ctx,
                                            TypedSymbol<Context> &sy) {
        return boost::apply_visitor( convert_to_bool_visitor<Context>(ctx, sy),
                                     sy.type );
      }

    } /* detail */
    /** \endcond **/

    template < typename Context >
    struct TypedSymbol {
      typedef typename Context::result_type result_type;

      TypedSymbol(logic::predicate p)
        : value(p)
        , type(Boolean())
      {}

      TypedSymbol(bv::bitvector bv, unsigned const w)
        : value(bv)
        , type(BitVector(w))
      {}

      TypedSymbol(result_type s,
                  any_type ty)
        : value(s)
      , type(ty)
      {}

      TypedSymbol(TypedSymbol<Context> const &other)
        : value(other.value)
        , type(other.type)
      {}

      bool operator==(TypedSymbol<Context> const &other) const {
        return (value == other.value &&
                type == other.type);
      }

      typename Context::result_type eval(Context &ctx) const {
        return detail::to_result_type(ctx, value);
      }

      // value == predicate && type == Boolean
      inline bool isPrimitiveBool() const {
        return detail::is_value<Context, logic::predicate>( value );
      }

      // value == bitvector && type == BitVector
      inline bool isPrimitiveBitVector() const {
        return detail::is_value<Context, bv::bitvector>( value );
      }

      inline bool isPrimitive() const {
        return isPrimitiveBool() || isPrimitiveBitVector();
      }

      inline bool isExpression() const {
        return detail::is_value<Context,typename Context::result_type>( value );
      }

      inline bool isBool() const {
        return detail::is_type<Boolean>( type );
      }

      inline bool isBitVector() const {
        return detail::is_type<BitVector>( type );
      }

      template < typename Type >
      inline Type getType(Type const &) const {
        return boost::get<Type>(type);
      }

      template < typename Type >
      inline Type getType() const {
        return boost::get<Type>(type);
      }

      inline typename Context::result_type toBV(Context &ctx) {
        return detail::to_bitvector(ctx, *this);
      }

      inline typename Context::result_type toBV(Context &ctx,
                                                unsigned const width) {
        if (isBool()) {
          return evaluate(ctx, bv::zero_extend(width-1,
                                           detail::to_bitvector(ctx, *this)));
        } else {
          BitVector bvtype = getType(BitVector());
          assert(width > bvtype.width);
          return evaluate(ctx, bv::zero_extend(width-bvtype.width,
                                           detail::to_bitvector(ctx, *this)));
        }
      }

      inline typename Context::result_type toBool(Context &ctx) {
        return detail::to_bool(ctx, *this);
      }

      typename detail::Expr<Context>::type value;
      any_type type;

    }; /* TypedSymbol */

  } /* type */

  /**@}*/

} /* metaSMT */
<|endoftext|>


<commit_before> // Copyright (c) 2009, Whispersoft s.r.l.
// 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 the name of Whispersoft s.r.l. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE 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 COPYRIGHT
// OWNER 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.
//
// Author: Cosmin Tudorache

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include "whisperlib/base/log.h"
// #include "whisperlib/base/common.h"
#include "whisperlib/base/core_errno.h"

#include "whisperlib/io/file/file.h"
#include "whisperlib/io/file/fd.h"

using namespace std;

#ifdef HAVE_LSEEK64
#define __LSEEK lseek64
#else
#define __LSEEK lseek
#endif

#ifdef HAVE_FDATASYNC
#define __FDATASYNC(fd) fdatasync(fd)
#else
  #ifdef F_FULLFSYNC
  #define __FDATASYNC(fd) fcntl((fd), F_FULLFSYNC)
  #else
  #define __FDATASYNC(fd) fsync(fd)
  #endif
#endif

#ifndef O_LARGEFILE
#define O_LARGEFILE 0;
#endif
#ifndef O_NOCTTY
#define O_NOCTTY 0
#endif

#if defined(HAVE_SYS_UIO_H)
static const int  kReadForWritevSize = 16384;
#endif

namespace whisper {
namespace io {

const char* File::AccessName(Access access) {
  switch ( access ) {
    CONSIDER(GENERIC_READ);
    CONSIDER(GENERIC_WRITE);
    CONSIDER(GENERIC_READ_WRITE);
  }
  return "UnknownAccess";
}

const char* File::CreationDispositionName(CreationDisposition cd) {
  switch ( cd ) {
    CONSIDER(CREATE_ALWAYS);
    CONSIDER(CREATE_NEW);
    CONSIDER(OPEN_ALWAYS);
    CONSIDER(OPEN_EXISTING);
    CONSIDER(TRUNCATE_EXISTING);
  }
  return "UnknownCreationDisposition";
}

const char* File::MoveMethodName(MoveMethod mm) {
  switch ( mm ) {
    CONSIDER(FILE_SET);
    CONSIDER(FILE_CUR);
    CONSIDER(FILE_END);
  }
  return "UnknownMoveMethod";
}

File::File()
  : filename_(""),
    fd_(INVALID_FD_VALUE),
    size_(0),
    position_(0) {
}

File::~File() {
  Close();
}

File* File::OpenFileOrDie(const char* filename) {
  File* const f = new File();
  CHECK(f->Open(filename, GENERIC_READ, OPEN_EXISTING));
  return f;
}

File* File::TryOpenFile(const char* filename) {
  File* const f = new File();
  if ( !f->Open(filename, GENERIC_READ, OPEN_EXISTING) ) {
    delete f;
    return NULL;
  }
  return f;
}

File* File::CreateFileOrDie(const char* filename) {
  File* const f = new File();
  CHECK(f->Open(filename, GENERIC_READ_WRITE, CREATE_ALWAYS));
  return f;
}
File* File::TryCreateFile(const char* filename) {
  File* const f = new File();
  if ( !f->Open(filename, GENERIC_READ_WRITE, CREATE_ALWAYS) ) {
    delete f;
    return NULL;
  }
  return f;
}

bool File::Open(const string& filename,  Access acc, CreationDisposition cd) {
  CHECK(!is_open());

  int flags = O_NOCTTY | O_LARGEFILE;
  switch ( cd ) {
  case CREATE_ALWAYS:     flags |= O_CREAT | O_TRUNC; break;
  case CREATE_NEW:        flags |= O_CREAT | O_EXCL; break;
  case OPEN_ALWAYS:       flags |= O_CREAT; break;
  case OPEN_EXISTING:     flags |= 0; break;
  case TRUNCATE_EXISTING: flags |= O_TRUNC; break;
  default:
    LOG_FATAL << filename << " - Invalid Disposition: " << cd;
  };

  mode_t mode = 0;
  switch ( acc )  {
  case GENERIC_READ:       flags |= O_RDONLY; mode = 00444; break;
  case GENERIC_WRITE:      flags |= O_WRONLY; mode = 00644; break;
  case GENERIC_READ_WRITE: flags |= O_RDWR;   mode = 00644; break;
  default:
    LOG_FATAL << filename << " Invalid Access: " << acc;
  };
  flags |= O_LARGEFILE;

  const int fd = ::open(filename.c_str(), flags, mode);
  if ( fd == INVALID_FD_VALUE ) {
    LOG_ERROR << "Cannot open file " << filename
              << " using access: " << AccessName(acc)
              << " creationDisposition: " << CreationDispositionName(cd)
              << " reason: " << GetLastSystemErrorDescription();
    return false;
  }

  filename_ = filename;
  fd_ = fd;
  UpdateSize();
  UpdatePosition();

  return true;
}
void File::Set(const string& filename, int fd) {
  filename_ = filename;
  fd_ = fd;
  UpdateSize();
  UpdatePosition();
}

void File::Close() {
  if ( !is_open() ) {
    return;
  }
  if ( ::close(fd_) < 0 ) {
    LOG_ERROR << filename_ << " - Error closing file."
              << " Reason: " << GetLastSystemErrorDescription();
  }
  fd_ = INVALID_FD_VALUE;
  filename_.clear();
  size_ = 0;
  position_ = 0;
}

uint64_t File::Size() const {
  CHECK(is_open());
  return size_;
}

uint64_t File::Position() const {
  CHECK(is_open());
  return position_;
}

int64_t File::SetPosition(int64_t distance,
                          MoveMethod move_method) {
  CHECK(is_open());
  int whence = SEEK_SET;
  switch ( move_method ) {
  case FILE_SET: whence = SEEK_SET; break;
  case FILE_CUR: whence = SEEK_CUR; break;
  case FILE_END: whence = SEEK_END; break;
  default:
    LOG_FATAL << filename_ << " Invalid MoveMethod : " << move_method;
  }

  const int64_t crt = ::__LSEEK(fd_, distance, whence);
  if ( crt < 0 ) {
    LOG_ERROR << filename_ << " lseek failed "
              << GetLastSystemErrorDescription();
    return -1;
  }
  // update cached position_
  position_ = uint64_t(crt);
  return position_;
}
void File::Rewind() {
    SetPosition(0, FILE_SET);
}

void File::Truncate(int64 pos) {
  if ( pos == -1 )  {
    pos = Position();
  }
  if ( ::ftruncate(fd_, pos) < 0 ) {
    LOG_ERROR << "::ftruncate() failed: " << GetLastSystemErrorDescription();
    return;
  }
  SetPosition(0, FILE_END);
  UpdateSize();
}

ssize_t File::ReadBuffer(void* buf, size_t len) {
  CHECK(is_open()) << filename_;
  const ssize_t cb = ::read(fd_, buf, len);
  if ( cb < 0 ) {
    LOG_ERROR << "::read() failed for file: [" << filename_
              << "], err: " << GetLastSystemErrorDescription();
    return cb;
  }
  position_ += cb;
  if ( size_ < position_ ) {
    // happens when the file gets bigger while we're reading
    UpdateSize();
  }
  return cb;
}

ssize_t File::Read(io::MemoryStream* out, size_t len) {
  char* buffer;
  ssize_t cb = 0;
  while ( size_t(cb) < len ) {
    size_t scratch;
    out->GetScratchSpace(&buffer, &scratch);
    if ( buffer == NULL ) {
        return -1;         // oom
    }
    const size_t cb_to_read = std::min(scratch, len - cb);
    const ssize_t cb_read = ReadBuffer(buffer, cb_to_read);
    if ( cb_read < 0 ) {
        out->ConfirmScratch(0);
        return cb_read;    // hard error
    }
    out->ConfirmScratch(cb_read);
    if ( cb_read == 0 ) {
        break;
    }
    cb += cb_read;
  }
  return cb;
}

void File::Skip(int64_t len) {
    SetPosition(len, FILE_CUR);
}

ssize_t File::WriteBuffer(const void* buf, size_t len) {
  DCHECK(is_open()) << filename_;
  const ssize_t cb = ::write(fd_, buf, len);
  if ( cb < 0 ) {
    LOG_ERROR << "::write() failed for file: [" << filename_
              << "], err: " << GetLastSystemErrorDescription();
    UpdatePosition();  // don't know where the file pointer ended-up
    return cb;
  }
  position_ += cb;
  size_ = std::max(size_, position_);
  return cb;
}

ssize_t File::Write(const string& s) {
  return WriteBuffer(s.data(), s.size());
}

ssize_t File::Write(io::MemoryStream* ms, ssize_t len) {
#if defined(HAVE_SYS_UIO_H)
  size_t scratch = 0;
  ssize_t cb = 0;
  while ( !ms->IsEmpty() && (len < 0 || cb < len) ) {
    ms->MarkerSet();
    struct ::iovec* iov = NULL;
    int iovcnt = 0;
    scratch = ms->ReadForWritev(&iov, &iovcnt,
                                (len < 0) ? kReadForWritevSize :
                                std::min(len - cb, ssize_t(kReadForWritevSize)));
    if ( iovcnt > 0 ) {
      const ssize_t crt_cb = ::writev(fd_, iov, iovcnt);
      delete [] iov;
      if ( crt_cb < 0 ) {
        ms->MarkerRestore();
        UpdatePosition();  // don't know where the file pointer ended-up
        size_ = std::max(size_, position_);
        return crt_cb;
      }
      if ( size_t(crt_cb) < scratch ) {
        // Written something but not all - we need to return and mark
        // the right amount in the buffer
        ms->MarkerRestore();
        ms->Skip(crt_cb);
      } else {
        // Everything written - no need for the marker
        ms->MarkerClear();
      }
      cb += crt_cb;
      if ( size_t(crt_cb) < scratch ) {
        break;
      }
    }
  }
  position_ += cb;
  size_ = std::max(size_, position_);
  return cb;
#else
  // Much slower version w/o writeev
  CHECK(is_open()) << filename_;
  if ( len < 0 ) {
    len = ms->Size();
  }
  const char* buf = NULL;
  size_t size = 0;
  ssize_t written = 0;

  while( len > 0 && ms->ReadNext(&buf, &size) ) {
    const size_t cb_to_write = std::min(len, size);
    const ssize_t cb_written = WriteBuffer(buf, cb_to_write);
    if ( cb_written < 0 ) {
      return cb_written;  // hard error
    }
    written += cb_written;
    if ( cb_written != cb_to_write ) {
      return written;     // whatever..
    }
    len -= cb_written;
  }
  return written;
#endif
}

void File::Flush() {
  CHECK(is_open()) << filename_;
  // Well this should not happen - we are screwed otherwise
  CHECK(::__FDATASYNC(fd_) != -1) << "::fdatasync() failed for file: ["
      << filename_ << "], err: " << GetLastSystemErrorDescription();
}

uint64_t File::UpdateSize() {
  const int64_t crt = ::__LSEEK(fd_, 0, SEEK_CUR);
  CHECK_GE(crt, 0) << GetLastSystemErrorDescription();
  const int64_t size =  ::__LSEEK(fd_, 0, SEEK_END);
  CHECK_GE(size, 0) << GetLastSystemErrorDescription();
  size_ = uint64_t(size);
  CHECK(::__LSEEK(fd_, crt, SEEK_SET) == crt)
      << " crt: " << crt << " - error: " << GetLastSystemErrorDescription();
  return size_;
}

uint64_t File::UpdatePosition() {
  const int64_t position = ::__LSEEK(fd_, 0, SEEK_CUR);
  CHECK_GE(position, 0) << GetLastSystemErrorDescription();
  position_ = uint64_t(position);
  return position_;
}
}  // namespace io
}  // namespace whisper
<commit_msg>Fixed osx build<commit_after> // Copyright (c) 2009, Whispersoft s.r.l.
// 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 the name of Whispersoft s.r.l. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE 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 COPYRIGHT
// OWNER 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.
//
// Author: Cosmin Tudorache

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include "whisperlib/base/log.h"
// #include "whisperlib/base/common.h"
#include "whisperlib/base/core_errno.h"

#include "whisperlib/io/file/file.h"
#include "whisperlib/io/file/fd.h"

using namespace std;

#ifdef HAVE_LSEEK64
#define __LSEEK lseek64
#else
#define __LSEEK lseek
#endif

#ifdef F_FULLFSYNC
# define __FDATASYNC(fd) fcntl((fd), F_FULLFSYNC)
#else
# ifdef HAVE_FDATASYNC
#  define __FDATASYNC(fd) fdatasync(fd)
# else
#  define __FDATASYNC(fd) fsync(fd)
# endif
#endif

#ifndef O_LARGEFILE
#define O_LARGEFILE 0;
#endif
#ifndef O_NOCTTY
#define O_NOCTTY 0
#endif

#if defined(HAVE_SYS_UIO_H)
static const int  kReadForWritevSize = 16384;
#endif

namespace whisper {
namespace io {

const char* File::AccessName(Access access) {
  switch ( access ) {
    CONSIDER(GENERIC_READ);
    CONSIDER(GENERIC_WRITE);
    CONSIDER(GENERIC_READ_WRITE);
  }
  return "UnknownAccess";
}

const char* File::CreationDispositionName(CreationDisposition cd) {
  switch ( cd ) {
    CONSIDER(CREATE_ALWAYS);
    CONSIDER(CREATE_NEW);
    CONSIDER(OPEN_ALWAYS);
    CONSIDER(OPEN_EXISTING);
    CONSIDER(TRUNCATE_EXISTING);
  }
  return "UnknownCreationDisposition";
}

const char* File::MoveMethodName(MoveMethod mm) {
  switch ( mm ) {
    CONSIDER(FILE_SET);
    CONSIDER(FILE_CUR);
    CONSIDER(FILE_END);
  }
  return "UnknownMoveMethod";
}

File::File()
  : filename_(""),
    fd_(INVALID_FD_VALUE),
    size_(0),
    position_(0) {
}

File::~File() {
  Close();
}

File* File::OpenFileOrDie(const char* filename) {
  File* const f = new File();
  CHECK(f->Open(filename, GENERIC_READ, OPEN_EXISTING));
  return f;
}

File* File::TryOpenFile(const char* filename) {
  File* const f = new File();
  if ( !f->Open(filename, GENERIC_READ, OPEN_EXISTING) ) {
    delete f;
    return NULL;
  }
  return f;
}

File* File::CreateFileOrDie(const char* filename) {
  File* const f = new File();
  CHECK(f->Open(filename, GENERIC_READ_WRITE, CREATE_ALWAYS));
  return f;
}
File* File::TryCreateFile(const char* filename) {
  File* const f = new File();
  if ( !f->Open(filename, GENERIC_READ_WRITE, CREATE_ALWAYS) ) {
    delete f;
    return NULL;
  }
  return f;
}

bool File::Open(const string& filename,  Access acc, CreationDisposition cd) {
  CHECK(!is_open());

  int flags = O_NOCTTY | O_LARGEFILE;
  switch ( cd ) {
  case CREATE_ALWAYS:     flags |= O_CREAT | O_TRUNC; break;
  case CREATE_NEW:        flags |= O_CREAT | O_EXCL; break;
  case OPEN_ALWAYS:       flags |= O_CREAT; break;
  case OPEN_EXISTING:     flags |= 0; break;
  case TRUNCATE_EXISTING: flags |= O_TRUNC; break;
  default:
    LOG_FATAL << filename << " - Invalid Disposition: " << cd;
  };

  mode_t mode = 0;
  switch ( acc )  {
  case GENERIC_READ:       flags |= O_RDONLY; mode = 00444; break;
  case GENERIC_WRITE:      flags |= O_WRONLY; mode = 00644; break;
  case GENERIC_READ_WRITE: flags |= O_RDWR;   mode = 00644; break;
  default:
    LOG_FATAL << filename << " Invalid Access: " << acc;
  };
  flags |= O_LARGEFILE;

  const int fd = ::open(filename.c_str(), flags, mode);
  if ( fd == INVALID_FD_VALUE ) {
    LOG_ERROR << "Cannot open file " << filename
              << " using access: " << AccessName(acc)
              << " creationDisposition: " << CreationDispositionName(cd)
              << " reason: " << GetLastSystemErrorDescription();
    return false;
  }

  filename_ = filename;
  fd_ = fd;
  UpdateSize();
  UpdatePosition();

  return true;
}
void File::Set(const string& filename, int fd) {
  filename_ = filename;
  fd_ = fd;
  UpdateSize();
  UpdatePosition();
}

void File::Close() {
  if ( !is_open() ) {
    return;
  }
  if ( ::close(fd_) < 0 ) {
    LOG_ERROR << filename_ << " - Error closing file."
              << " Reason: " << GetLastSystemErrorDescription();
  }
  fd_ = INVALID_FD_VALUE;
  filename_.clear();
  size_ = 0;
  position_ = 0;
}

uint64_t File::Size() const {
  CHECK(is_open());
  return size_;
}

uint64_t File::Position() const {
  CHECK(is_open());
  return position_;
}

int64_t File::SetPosition(int64_t distance,
                          MoveMethod move_method) {
  CHECK(is_open());
  int whence = SEEK_SET;
  switch ( move_method ) {
  case FILE_SET: whence = SEEK_SET; break;
  case FILE_CUR: whence = SEEK_CUR; break;
  case FILE_END: whence = SEEK_END; break;
  default:
    LOG_FATAL << filename_ << " Invalid MoveMethod : " << move_method;
  }

  const int64_t crt = ::__LSEEK(fd_, distance, whence);
  if ( crt < 0 ) {
    LOG_ERROR << filename_ << " lseek failed "
              << GetLastSystemErrorDescription();
    return -1;
  }
  // update cached position_
  position_ = uint64_t(crt);
  return position_;
}
void File::Rewind() {
    SetPosition(0, FILE_SET);
}

void File::Truncate(int64 pos) {
  if ( pos == -1 )  {
    pos = Position();
  }
  if ( ::ftruncate(fd_, pos) < 0 ) {
    LOG_ERROR << "::ftruncate() failed: " << GetLastSystemErrorDescription();
    return;
  }
  SetPosition(0, FILE_END);
  UpdateSize();
}

ssize_t File::ReadBuffer(void* buf, size_t len) {
  CHECK(is_open()) << filename_;
  const ssize_t cb = ::read(fd_, buf, len);
  if ( cb < 0 ) {
    LOG_ERROR << "::read() failed for file: [" << filename_
              << "], err: " << GetLastSystemErrorDescription();
    return cb;
  }
  position_ += cb;
  if ( size_ < position_ ) {
    // happens when the file gets bigger while we're reading
    UpdateSize();
  }
  return cb;
}

ssize_t File::Read(io::MemoryStream* out, size_t len) {
  char* buffer;
  ssize_t cb = 0;
  while ( size_t(cb) < len ) {
    size_t scratch;
    out->GetScratchSpace(&buffer, &scratch);
    if ( buffer == NULL ) {
        return -1;         // oom
    }
    const size_t cb_to_read = std::min(scratch, len - cb);
    const ssize_t cb_read = ReadBuffer(buffer, cb_to_read);
    if ( cb_read < 0 ) {
        out->ConfirmScratch(0);
        return cb_read;    // hard error
    }
    out->ConfirmScratch(cb_read);
    if ( cb_read == 0 ) {
        break;
    }
    cb += cb_read;
  }
  return cb;
}

void File::Skip(int64_t len) {
    SetPosition(len, FILE_CUR);
}

ssize_t File::WriteBuffer(const void* buf, size_t len) {
  DCHECK(is_open()) << filename_;
  const ssize_t cb = ::write(fd_, buf, len);
  if ( cb < 0 ) {
    LOG_ERROR << "::write() failed for file: [" << filename_
              << "], err: " << GetLastSystemErrorDescription();
    UpdatePosition();  // don't know where the file pointer ended-up
    return cb;
  }
  position_ += cb;
  size_ = std::max(size_, position_);
  return cb;
}

ssize_t File::Write(const string& s) {
  return WriteBuffer(s.data(), s.size());
}

ssize_t File::Write(io::MemoryStream* ms, ssize_t len) {
#if defined(HAVE_SYS_UIO_H)
  size_t scratch = 0;
  ssize_t cb = 0;
  while ( !ms->IsEmpty() && (len < 0 || cb < len) ) {
    ms->MarkerSet();
    struct ::iovec* iov = NULL;
    int iovcnt = 0;
    scratch = ms->ReadForWritev(&iov, &iovcnt,
                                (len < 0) ? kReadForWritevSize :
                                std::min(len - cb, ssize_t(kReadForWritevSize)));
    if ( iovcnt > 0 ) {
      const ssize_t crt_cb = ::writev(fd_, iov, iovcnt);
      delete [] iov;
      if ( crt_cb < 0 ) {
        ms->MarkerRestore();
        UpdatePosition();  // don't know where the file pointer ended-up
        size_ = std::max(size_, position_);
        return crt_cb;
      }
      if ( size_t(crt_cb) < scratch ) {
        // Written something but not all - we need to return and mark
        // the right amount in the buffer
        ms->MarkerRestore();
        ms->Skip(crt_cb);
      } else {
        // Everything written - no need for the marker
        ms->MarkerClear();
      }
      cb += crt_cb;
      if ( size_t(crt_cb) < scratch ) {
        break;
      }
    }
  }
  position_ += cb;
  size_ = std::max(size_, position_);
  return cb;
#else
  // Much slower version w/o writeev
  CHECK(is_open()) << filename_;
  if ( len < 0 ) {
    len = ms->Size();
  }
  const char* buf = NULL;
  size_t size = 0;
  ssize_t written = 0;

  while( len > 0 && ms->ReadNext(&buf, &size) ) {
    const size_t cb_to_write = std::min(len, size);
    const ssize_t cb_written = WriteBuffer(buf, cb_to_write);
    if ( cb_written < 0 ) {
      return cb_written;  // hard error
    }
    written += cb_written;
    if ( cb_written != cb_to_write ) {
      return written;     // whatever..
    }
    len -= cb_written;
  }
  return written;
#endif
}

void File::Flush() {
  CHECK(is_open()) << filename_;
  // Well this should not happen - we are screwed otherwise
  CHECK(::__FDATASYNC(fd_) != -1) << "::fdatasync() failed for file: ["
      << filename_ << "], err: " << GetLastSystemErrorDescription();
}

uint64_t File::UpdateSize() {
  const int64_t crt = ::__LSEEK(fd_, 0, SEEK_CUR);
  CHECK_GE(crt, 0) << GetLastSystemErrorDescription();
  const int64_t size =  ::__LSEEK(fd_, 0, SEEK_END);
  CHECK_GE(size, 0) << GetLastSystemErrorDescription();
  size_ = uint64_t(size);
  CHECK(::__LSEEK(fd_, crt, SEEK_SET) == crt)
      << " crt: " << crt << " - error: " << GetLastSystemErrorDescription();
  return size_;
}

uint64_t File::UpdatePosition() {
  const int64_t position = ::__LSEEK(fd_, 0, SEEK_CUR);
  CHECK_GE(position, 0) << GetLastSystemErrorDescription();
  position_ = uint64_t(position);
  return position_;
}
}  // namespace io
}  // namespace whisper
<|endoftext|>


<commit_before>/*
 * arcemu MMORPG Server
 * Voice Chat Engine
 * Copyright (C) 2005-2007 Burlex <burlex@gmail.com>
 *
 * This program 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
 * any later version.
 *
 * This program 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 this program.  If not, see <http://www.gnu.org/licenses/>.
 *
 */

#include "StdAfx.h"

#ifdef VOICE_CHAT

VoiceChatClientSocket::VoiceChatClientSocket(uint32 fd) : Socket(fd, 250000, 250000)
{
	remaining = 0;
	op = 0;
	next_ping = UNIXTIME + 15;
	last_pong = UNIXTIME;
}

void VoiceChatClientSocket::OnDisconnect()
{
	sVoiceChatHandler.SocketDisconnected();
}

void VoiceChatClientSocket::OnRead()
{
	WorldPacket *data;

	// uint16 op
	// uint16 size
	// <data>

	for(;;)
	{
		// no more data
		if( GetReadBufferSize() < 4 )
			break;

		Read(2, (uint8*)&op);
		Read(2, (uint8*)&remaining);

		if( GetReadBufferSize() < remaining )
			break;

		data = new WorldPacket(op, remaining);
		data->resize(remaining);
		Read(remaining, (uint8*)data->contents());

		// handle the packet
		sVoiceChatHandler.OnRead(data);

		delete data;
		remaining = op = 0;
	}
}

void VoiceChatClientSocket::SendPacket(WorldPacket* data)
{
	if( m_writeByteCount + 4 + data->size() > m_writeBufferSize )
	{
		printf("!!! VOICE CHAT CLIENT SOCKET OVERLOAD !!!\n");
		return;
	}
	uint16 opcode = data->GetOpcode();
	uint32 sz = data->size();
	bool rv;

	BurstBegin();
	rv = BurstSend((const uint8*)&opcode, 2);
	if(rv) BurstSend((const uint8*)&sz, 2);

	if( sz > 0 && rv )
	{
		rv = BurstSend((const uint8*)data->contents(), data->size());
	}

	printf("sent packet of %u bytes with op %u, buffer len is now %u\n", data->size(), data->GetOpcode(), m_writeByteCount);
	if( rv )
		BurstPush();

	BurstEnd();
}

#endif		// VOICE_CHAT
<commit_msg>http://arcemu.org/forums/index.php?showtopic=2343&hl= -> voichat compile fix<commit_after>/*
 * arcemu MMORPG Server
 * Voice Chat Engine
 * Copyright (C) 2005-2007 Burlex <burlex@gmail.com>
 *
 * This program 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
 * any later version.
 *
 * This program 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 this program.  If not, see <http://www.gnu.org/licenses/>.
 *
 */

#include "StdAfx.h"

#ifdef VOICE_CHAT

VoiceChatClientSocket::VoiceChatClientSocket(uint32 fd) : Socket(fd, 250000, 250000)
{
	remaining = 0;
	op = 0;
	next_ping = UNIXTIME + 15;
	last_pong = UNIXTIME;
}

void VoiceChatClientSocket::OnDisconnect()
{
	sVoiceChatHandler.SocketDisconnected();
}

void VoiceChatClientSocket::OnRead()
{
	WorldPacket *data;

	// uint16 op
	// uint16 size
	// <data>

	for(;;)
	{
		// no more data
		if( GetReadBuffer().GetSize() < 4 )
			break;

		GetReadBuffer().Read((uint8*)&op, 2);
		GetReadBuffer().Read((uint8*)&remaining, 2);

		if( GetReadBuffer().GetSize() < remaining )
			break;

		data = new WorldPacket(op, remaining);
		data->resize(remaining);
		GetReadBuffer().Read((uint8*)data->contents(), remaining);

		// handle the packet
		sVoiceChatHandler.OnRead(data);

		delete data;
		remaining = op = 0;
	}
}

void VoiceChatClientSocket::SendPacket(WorldPacket* data)
{
	//if((m_writeByteCount + len + 4) >= m_writeBufferSize)
	//if( GetWriteBuffer().GetSpace() < (len+4) )
	//if( m_writeByteCount + 4 + data->size() > m_writeBufferSize )
	if(	GetWriteBuffer().GetSpace() < (data->size()+4) )
	{
		Log.Error("VoiceChatHandler","!!! VOICE CHAT CLIENT SOCKET OVERLOAD !!!");
		return;
	}
	uint16 opcode = data->GetOpcode();
	uint32 sz = (uint32)data->size();
	bool rv;

	BurstBegin();
	rv = BurstSend((const uint8*)&opcode, 2);
	if(rv) BurstSend((const uint8*)&sz, 2);

	if( sz > 0 && rv )
	{
		rv = BurstSend((const uint8*)data->contents(), (uint32)data->size());
	}

	Log.Debug("VoiceChatHandler","sent packet of %u bytes with op %u, buffer len is now %u", data->size(), data->GetOpcode(), GetWriteBuffer().GetSize());
	if( rv )
		BurstPush();

	BurstEnd();
}

#endif		// VOICE_CHAT
<|endoftext|>


<commit_before>#include <iostream>
#include <iomanip>
#include "generated_test_two_kernels_rs.h"

buffer_t make_interleaved_image(int width, int height, int channels, uint8_t host[]) {
    buffer_t bt_input = { 0 };
    bt_input.host = (uint8_t*)&host[0];
    bt_input.stride[0] = channels;
    bt_input.extent[0] = width;
    bt_input.stride[1] = channels * width;
    bt_input.extent[1] = height;
    bt_input.stride[2] = 1;
    bt_input.extent[2] = channels;
    bt_input.elem_size = sizeof(uint8_t);
    return bt_input;
}

void print(buffer_t bt) {
    for (int j = 0; j < std::min(bt.extent[1], 10); j++) {
        for (int i = 0; i < std::min(bt.extent[0], 10); i++) {
            std::cout << " [";
            for (int k = 0; k < bt.extent[2]; k++) {
                std::cout << std::fixed << std::setprecision(1);
                if (k > 0) {
                    std::cout << std::setw(4);
                }
                std::cout << +((uint8_t*)bt.host)[i * bt.stride[0] +
                                                  j * bt.stride[1] +
                                                  k * bt.stride[2]];
            }
            std::cout << "]";
        }

        std::cout << std::endl;
    }
}

extern "C" void halide_set_renderscript_cache_dir(const char *c);
extern "C" int halide_copy_to_host(void *, buffer_t *);

int main(int argc, char** argv) {
    const char *cacheDir = "/data/tmp";
    halide_set_renderscript_cache_dir(cacheDir);

    int width = 10;
    int height = 10;
    int channels = 4;
    uint8_t *input = (uint8_t*)malloc(sizeof(uint8_t) * width * height * channels);
    uint8_t *output = (uint8_t*)malloc(sizeof(uint8_t) * width * height * channels);

    buffer_t input_buft = make_interleaved_image(width, height, channels, input);
    for (int i = 0; i < std::min(input_buft.extent[0], width); i++) {
        for (int j = 0; j < std::min(input_buft.extent[1], height); j++) {
            for (int k = 0; k < input_buft.extent[2]; k++) {
                input[i * input_buft.stride[0] +
                      j * input_buft.stride[1] +
                      k * input_buft.stride[2]] = ((i + j) % 2) * 6;
            }
        }
    }

    std::cout << "Input :\n";
    print(input_buft);

    buffer_t output_buft = make_interleaved_image(width, height, channels, output);

    input_buft.host_dirty = true;
    generated_test_two_kernels_rs(&input_buft, &output_buft);
    halide_copy_to_host(NULL, &output_buft);

    std::cout << "Output :\n";
    print(output_buft);
}
<commit_msg>Add output validation.<commit_after>#include <iostream>
#include <iomanip>
#include "generated_test_two_kernels_rs.h"

buffer_t make_interleaved_image(int width, int height, int channels, uint8_t host[]) {
    buffer_t bt_input = { 0 };
    bt_input.host = (uint8_t*)&host[0];
    bt_input.stride[0] = channels;
    bt_input.extent[0] = width;
    bt_input.stride[1] = channels * width;
    bt_input.extent[1] = height;
    bt_input.stride[2] = 1;
    bt_input.extent[2] = channels;
    bt_input.elem_size = sizeof(uint8_t);
    return bt_input;
}

void print(buffer_t bt) {
    for (int j = 0; j < std::min(bt.extent[1], 10); j++) {
        for (int i = 0; i < std::min(bt.extent[0], 10); i++) {
            std::cout << " [";
            for (int k = 0; k < bt.extent[2]; k++) {
                std::cout << std::fixed << std::setprecision(1);
                if (k > 0) {
                    std::cout << std::setw(4);
                }
                std::cout << +((uint8_t*)bt.host)[i * bt.stride[0] +
                                                  j * bt.stride[1] +
                                                  k * bt.stride[2]];
            }
            std::cout << "]";
        }

        std::cout << std::endl;
    }
}

extern "C" void halide_set_renderscript_cache_dir(const char *c);
extern "C" int halide_copy_to_host(void *, buffer_t *);

int main(int argc, char** argv) {
    const char *cacheDir = "/data/tmp";
    halide_set_renderscript_cache_dir(cacheDir);

    int width = 10;
    int height = 10;
    int channels = 4;
    uint8_t *input = (uint8_t*)malloc(sizeof(uint8_t) * width * height * channels);
    uint8_t *output = (uint8_t*)malloc(sizeof(uint8_t) * width * height * channels);

    buffer_t input_buft = make_interleaved_image(width, height, channels, input);
    for (int i = 0; i < std::min(input_buft.extent[0], width); i++) {
        for (int j = 0; j < std::min(input_buft.extent[1], height); j++) {
            for (int k = 0; k < input_buft.extent[2]; k++) {
                input[i * input_buft.stride[0] +
                      j * input_buft.stride[1] +
                      k * input_buft.stride[2]] = ((i + j) % 2) * 6;
            }
        }
    }

    std::cout << "Input :\n";
    print(input_buft);

    buffer_t output_buft = make_interleaved_image(width, height, channels, output);

    input_buft.host_dirty = true;
    generated_test_two_kernels_rs(&input_buft, &output_buft);
    halide_copy_to_host(NULL, &output_buft);

    std::cout << "Output :\n";
    print(output_buft);

    bool test_pass = true;
    for (int i = 0; i < std::min(input_buft.extent[0], width); i++) {
        for (int j = 0; j < std::min(input_buft.extent[1], height); j++) {
            for (int k = 0; k < input_buft.extent[2]; k++) {
                uint8_t input_value = input[i * input_buft.stride[0] +
                                            j * input_buft.stride[1] +
                                            k * input_buft.stride[2]];
                uint8_t output_value = output[i * input_buft.stride[0] +
                                              j * input_buft.stride[1] +
                                              k * input_buft.stride[2]];
                if (input_value != output_value) {
                    std::cout << "Mismatch at (" << i << ", " << j << ", " << k << "): " <<
                        " input=" << (+input_value) << " output=" << (+output_value) << "\n";
                    test_pass = false;
                }
            }
        }
    }

    std::cout << (test_pass? "Test passed.\n": "Test failed.\n");
}
<|endoftext|>