<commit_before>// Copyright 2021 The XLS Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

// This file contains the  main function (entry point) of the xlscc
// front-end. It accepts as input a C/C++ file and produces as textual output
// the equivalent XLS intermediate representation (IR).

#include <cstdlib>
#include <fstream>
#include <streambuf>

#include "absl/flags/flag.h"
#include "absl/status/status.h"
#include "absl/strings/str_format.h"
#include "absl/strings/str_split.h"
#include "clang/include/clang/AST/Attr.h"
#include "clang/include/clang/AST/Decl.h"
#include "clang/include/clang/AST/DeclCXX.h"
#include "clang/include/clang/AST/Expr.h"
#include "clang/include/clang/AST/Stmt.h"
#include "xls/codegen/block_conversion.h"
#include "xls/codegen/block_generator.h"
#include "xls/common/init_xls.h"
#include "xls/common/logging/logging.h"
#include "xls/common/status/status_macros.h"
#include "xls/contrib/xlscc/hls_block.pb.h"
#include "xls/contrib/xlscc/metadata_output.pb.h"
#include "xls/contrib/xlscc/translator.h"
#include "xls/ir/block.h"
#include "xls/passes/standard_pipeline.h"

const char kUsage[] = R"(
Generates XLS IR from a given C++ file, or generates Verilog in the special
case of a combinational module.

Emit XLS IR:
xlscc foo.cc

Emit combinational Verilog module:
xlscc foo.cc --block_pb block_info.pb

)";

ABSL_FLAG(std::string, module_name, "",
          "Explicit name to use for the generated module; if not provided the "
          "mangled IR function name is used");

ABSL_FLAG(std::string, block_pb, "",
          "HLSBlock protobuf for generating as HLS block / XLS proc");

ABSL_FLAG(std::string, top, "", "Top function name");

ABSL_FLAG(std::string, package, "", "Package name to generate");

ABSL_FLAG(std::string, clang_args_file, "",
          "File containing on each line one command line argument for clang");

ABSL_FLAG(std::vector<std::string>, defines, std::vector<std::string>(),
          "Comma separated list of defines to pass to clang");

ABSL_FLAG(std::vector<std::string>, include_dirs, std::vector<std::string>(),
          "Comma separated list of include directories to pass to clang");

ABSL_FLAG(std::string, meta_out, "",
          "Path at which to output metadata protobuf");

ABSL_FLAG(bool, dump_ir_only, false,
          "Output proc IR and do not continue to block/verilog generation");

namespace xlscc {

absl::Status Run(absl::string_view cpp_path) {
  xlscc::Translator translator;

  const std::string block_pb_name = absl::GetFlag(FLAGS_block_pb);

  HLSBlock block;
  if (!block_pb_name.empty()) {
    std::ifstream file_in(block_pb_name);
    if (!block.ParseFromIstream(&file_in)) {
      return absl::InvalidArgumentError("Couldn't parse protobuf");
    }
  }

  const std::string top_function_name = absl::GetFlag(FLAGS_top);

  if (!top_function_name.empty()) {
    XLS_RETURN_IF_ERROR(translator.SelectTop(top_function_name));
  }

  std::vector<std::string> clang_argvs;

  const std::string clang_args_file = absl::GetFlag(FLAGS_clang_args_file);

  if (!clang_args_file.empty()) {
    XLS_ASSIGN_OR_RETURN(std::string clang_args_content,
                         xls::GetFileContents(clang_args_file));
    for (auto arg :
         absl::StrSplit(clang_args_content, '\n', absl::SkipWhitespace())) {
      clang_argvs.push_back(std::string(absl::StripAsciiWhitespace(arg)));
    }
  }

  for (std::string& def : absl::GetFlag(FLAGS_defines)) {
    clang_argvs.push_back(absl::StrCat("-D", def));
  }

  for (std::string& dir : absl::GetFlag(FLAGS_include_dirs)) {
    clang_argvs.push_back(absl::StrCat("-I", dir));
  }

  std::vector<absl::string_view> clang_argv;
  for (size_t i = 0; i < clang_argvs.size(); ++i) {
    clang_argv.push_back(clang_argvs[i]);
  }

  std::cerr << "Parsing file '" << cpp_path << "' with clang..." << std::endl;
  XLS_RETURN_IF_ERROR(translator.ScanFile(
      cpp_path, clang_argv.empty()
                    ? absl::Span<absl::string_view>()
                    : absl::MakeSpan(&clang_argv[0], clang_argv.size())));

  XLS_ASSIGN_OR_RETURN(absl::StatusOr<std::string> top_name,
                       translator.GetEntryFunctionName());

  std::string package_name = absl::GetFlag(FLAGS_package);

  if (package_name.empty()) {
    package_name = "my_package";
  } else {
    package_name = top_name.value();
  }

  std::cerr << "Generating IR..." << std::endl;
  xls::Package package(package_name, top_name.value());
  if (block_pb_name.empty()) {
    XLS_RETURN_IF_ERROR(translator.GenerateIR_Top_Function(&package).status());
    // TODO(seanhaskell): Simplify IR
    std::cout << package.DumpIr() << std::endl;
  } else {
    XLS_ASSIGN_OR_RETURN(xls::Proc * proc,
                         translator.GenerateIR_Block(&package, block));

    if (absl::GetFlag(FLAGS_dump_ir_only)) {
      std::cerr << "Saving Package IR..." << std::endl;
      std::cout << package.DumpIr() << std::endl;
    } else {
      XLS_RETURN_IF_ERROR(translator.InlineAllInvokes(&package));

      xls::verilog::CodegenOptions codegen_options;
      codegen_options.use_system_verilog(false);

      XLS_ASSIGN_OR_RETURN(xls::Block * xls_block,
                           xls::verilog::ProcToCombinationalBlock(
                               proc, proc->name(), codegen_options));
      std::cerr << "Generating Verilog..." << std::endl;
      XLS_ASSIGN_OR_RETURN(
          std::string verilog,
          xls::verilog::GenerateVerilog(xls_block, codegen_options));

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

  const std::string metadata_out_path = absl::GetFlag(FLAGS_meta_out);
  if (!metadata_out_path.empty()) {
    XLS_ASSIGN_OR_RETURN(xlscc_metadata::MetadataOutput meta,
                         translator.GenerateMetadata());
    std::ofstream ostr(metadata_out_path);
    if (!ostr.good()) {
      return absl::NotFoundError(absl::StrFormat(
          "Couldn't open metadata output path: %s", metadata_out_path));
    }
    if (!meta.SerializeToOstream(&ostr)) {
      return absl::UnknownError("Error writing metadata proto");
    }
  }

  return absl::OkStatus();
}

}  // namespace xlscc

int main(int argc, char** argv) {
  std::vector<absl::string_view> positional_arguments =
      xls::InitXls(kUsage, argc, argv);

  if (positional_arguments.size() != 1) {
    XLS_LOG(QFATAL) << absl::StreamFormat("Expected invocation: %s CPP_FILE",
                                          argv[0]);
  }
  absl::string_view cpp_path = positional_arguments[0];
  //  XLS_QCHECK_OK(xlscc::Run(cpp_path));
  absl::Status status = xlscc::Run(cpp_path);
  if (!status.ok()) {
    std::cerr << status.ToString() << std::endl;
    return EXIT_FAILURE;
  }
  return EXIT_SUCCESS;
}
<commit_msg>[XLSCC] Remove unused module_name flag. Enable package_name provided by user to be the package name of the IR.<commit_after>// Copyright 2021 The XLS Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

// This file contains the  main function (entry point) of the xlscc
// front-end. It accepts as input a C/C++ file and produces as textual output
// the equivalent XLS intermediate representation (IR).

#include <cstdlib>
#include <fstream>
#include <streambuf>

#include "absl/flags/flag.h"
#include "absl/status/status.h"
#include "absl/strings/str_format.h"
#include "absl/strings/str_split.h"
#include "clang/include/clang/AST/Attr.h"
#include "clang/include/clang/AST/Decl.h"
#include "clang/include/clang/AST/DeclCXX.h"
#include "clang/include/clang/AST/Expr.h"
#include "clang/include/clang/AST/Stmt.h"
#include "xls/codegen/block_conversion.h"
#include "xls/codegen/block_generator.h"
#include "xls/common/init_xls.h"
#include "xls/common/logging/logging.h"
#include "xls/common/status/status_macros.h"
#include "xls/contrib/xlscc/hls_block.pb.h"
#include "xls/contrib/xlscc/metadata_output.pb.h"
#include "xls/contrib/xlscc/translator.h"
#include "xls/ir/block.h"
#include "xls/passes/standard_pipeline.h"

const char kUsage[] = R"(
Generates XLS IR from a given C++ file, or generates Verilog in the special
case of a combinational module.

Emit XLS IR:
xlscc foo.cc

Emit combinational Verilog module:
xlscc foo.cc --block_pb block_info.pb

)";

ABSL_FLAG(std::string, block_pb, "",
          "HLSBlock protobuf for generating as HLS block / XLS proc");

ABSL_FLAG(std::string, top, "", "Top function name");

ABSL_FLAG(std::string, package, "", "Package name to generate");

ABSL_FLAG(std::string, clang_args_file, "",
          "File containing on each line one command line argument for clang");

ABSL_FLAG(std::vector<std::string>, defines, std::vector<std::string>(),
          "Comma separated list of defines to pass to clang");

ABSL_FLAG(std::vector<std::string>, include_dirs, std::vector<std::string>(),
          "Comma separated list of include directories to pass to clang");

ABSL_FLAG(std::string, meta_out, "",
          "Path at which to output metadata protobuf");

ABSL_FLAG(bool, dump_ir_only, false,
          "Output proc IR and do not continue to block/verilog generation");

namespace xlscc {

absl::Status Run(absl::string_view cpp_path) {
  xlscc::Translator translator;

  const std::string block_pb_name = absl::GetFlag(FLAGS_block_pb);

  HLSBlock block;
  if (!block_pb_name.empty()) {
    std::ifstream file_in(block_pb_name);
    if (!block.ParseFromIstream(&file_in)) {
      return absl::InvalidArgumentError("Couldn't parse protobuf");
    }
  }

  const std::string top_function_name = absl::GetFlag(FLAGS_top);

  if (!top_function_name.empty()) {
    XLS_RETURN_IF_ERROR(translator.SelectTop(top_function_name));
  }

  std::vector<std::string> clang_argvs;

  const std::string clang_args_file = absl::GetFlag(FLAGS_clang_args_file);

  if (!clang_args_file.empty()) {
    XLS_ASSIGN_OR_RETURN(std::string clang_args_content,
                         xls::GetFileContents(clang_args_file));
    for (auto arg :
         absl::StrSplit(clang_args_content, '\n', absl::SkipWhitespace())) {
      clang_argvs.push_back(std::string(absl::StripAsciiWhitespace(arg)));
    }
  }

  for (std::string& def : absl::GetFlag(FLAGS_defines)) {
    clang_argvs.push_back(absl::StrCat("-D", def));
  }

  for (std::string& dir : absl::GetFlag(FLAGS_include_dirs)) {
    clang_argvs.push_back(absl::StrCat("-I", dir));
  }

  std::vector<absl::string_view> clang_argv;
  for (size_t i = 0; i < clang_argvs.size(); ++i) {
    clang_argv.push_back(clang_argvs[i]);
  }

  std::cerr << "Parsing file '" << cpp_path << "' with clang..." << std::endl;
  XLS_RETURN_IF_ERROR(translator.ScanFile(
      cpp_path, clang_argv.empty()
                    ? absl::Span<absl::string_view>()
                    : absl::MakeSpan(&clang_argv[0], clang_argv.size())));

  XLS_ASSIGN_OR_RETURN(absl::StatusOr<std::string> top_name,
                       translator.GetEntryFunctionName());

  std::string package_name = absl::GetFlag(FLAGS_package);

  if (package_name.empty()) {
    package_name = "my_package";
  }

  std::cerr << "Generating IR..." << std::endl;
  xls::Package package(package_name, top_name.value());
  if (block_pb_name.empty()) {
    XLS_RETURN_IF_ERROR(translator.GenerateIR_Top_Function(&package).status());
    // TODO(seanhaskell): Simplify IR
    std::cout << package.DumpIr() << std::endl;
  } else {
    XLS_ASSIGN_OR_RETURN(xls::Proc * proc,
                         translator.GenerateIR_Block(&package, block));

    if (absl::GetFlag(FLAGS_dump_ir_only)) {
      std::cerr << "Saving Package IR..." << std::endl;
      std::cout << package.DumpIr() << std::endl;
    } else {
      XLS_RETURN_IF_ERROR(translator.InlineAllInvokes(&package));

      xls::verilog::CodegenOptions codegen_options;
      codegen_options.use_system_verilog(false);

      XLS_ASSIGN_OR_RETURN(xls::Block * xls_block,
                           xls::verilog::ProcToCombinationalBlock(
                               proc, proc->name(), codegen_options));
      std::cerr << "Generating Verilog..." << std::endl;
      XLS_ASSIGN_OR_RETURN(
          std::string verilog,
          xls::verilog::GenerateVerilog(xls_block, codegen_options));

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

  const std::string metadata_out_path = absl::GetFlag(FLAGS_meta_out);
  if (!metadata_out_path.empty()) {
    XLS_ASSIGN_OR_RETURN(xlscc_metadata::MetadataOutput meta,
                         translator.GenerateMetadata());
    std::ofstream ostr(metadata_out_path);
    if (!ostr.good()) {
      return absl::NotFoundError(absl::StrFormat(
          "Couldn't open metadata output path: %s", metadata_out_path));
    }
    if (!meta.SerializeToOstream(&ostr)) {
      return absl::UnknownError("Error writing metadata proto");
    }
  }

  return absl::OkStatus();
}

}  // namespace xlscc

int main(int argc, char** argv) {
  std::vector<absl::string_view> positional_arguments =
      xls::InitXls(kUsage, argc, argv);

  if (positional_arguments.size() != 1) {
    XLS_LOG(QFATAL) << absl::StreamFormat("Expected invocation: %s CPP_FILE",
                                          argv[0]);
  }
  absl::string_view cpp_path = positional_arguments[0];
  //  XLS_QCHECK_OK(xlscc::Run(cpp_path));
  absl::Status status = xlscc::Run(cpp_path);
  if (!status.ok()) {
    std::cerr << status.ToString() << std::endl;
    return EXIT_FAILURE;
  }
  return EXIT_SUCCESS;
}
<|endoftext|>


<commit_before>#include "binson.hpp"

#include <binson_light.h>

#include <string.h>
#include <stdexcept>

using namespace std;

#define IF_RUNTIME_ERROR(x, msg) if (!(x)) throw std::runtime_error(msg)

const std::array<std::string, 8> BinsonValue::typeToString =
{
    "noneType",
    "boolType",
    "intType",
    "doubleType",
    "stringType",
    "binaryType",
    "objectType",
    "arrayType",
};

Binson & Binson::put(const std::string &key, const BinsonValue &v)
{
    m_items[key] = move(v);
    return *this;
}

Binson & Binson::put(const std::string &key, Binson o)
{
    m_items[key] = BinsonValue(move(o));
    return *this;
}

Binson & Binson::put(const string &key, const uint8_t *data, size_t size)
{
    vector<uint8_t> v(data, data + size);
    m_items[key] = move(BinsonValue(move(v)));
    return *this;
}

const BinsonValue Binson::get(const string &key) const
{
    if (!hasKey(key))
        throw std::out_of_range("Key '" + key + "' does not exist");
    else
        return m_items.at(key);
}

bool Binson::hasKey(const string &key) const
{
    return m_items.find(key) != m_items.end();
}

void Binson::clear()
{
    m_items.clear();
}

void Binson::seralizeItem(binson_writer *w, const BinsonValue &val) const
{
    switch(val.myType())
    {
    case BinsonValue::Types::noneType:
        break;
    case BinsonValue::Types::boolType:
        binson_write_boolean(w, val.getBool());
        break;
    case BinsonValue::Types::intType:
        binson_write_integer(w, val.getInt());
        break;
    case BinsonValue::Types::doubleType:
        binson_write_double(w, val.getDouble());
        break;
    case BinsonValue::Types::stringType:
        binson_write_string_with_len(w,
                                     val.getString().data(),
                                     val.getString().size());
        break;
    case BinsonValue::Types::binaryType:
        binson_write_bytes(w, val.getBin().data(), val.getBin().size());
        break;
    case BinsonValue::Types::objectType:
        binson_write_object_begin(w);
        val.getObject().seralizeItems(w);
        binson_write_object_end(w);
        break;
    case BinsonValue::Types::arrayType:
        binson_write_array_begin(w);
        for (auto &arrayValue : val.getArray())
        {
            seralizeItem(w, arrayValue);
        }
        binson_write_array_end(w);
        break;
    default:
        throw runtime_error("Unknown binson type");
    }
}

void Binson::seralizeItems(binson_writer *w) const
{
    for (auto &item: m_items)
    {
        binson_write_name_with_len(w, item.first.c_str(), item.first.size());
        seralizeItem(w, item.second);
    }
}

std::vector<uint8_t> Binson::serialize() const
{
    vector<uint8_t> data;
    data.resize(1000);
    binson_writer w;
    binson_writer_init(&w, data.data(), data.size());
    serialize(&w);
    if (w.error_flags == BINSON_ERROR_RANGE)
    {
        data.resize(binson_writer_get_counter(&w));
        binson_writer_init(&w, data.data(), data.size());
        serialize(&w);
    }

    if (w.error_flags == BINSON_ERROR_NONE)
        data.resize(binson_writer_get_counter(&w));
    else
        data.clear();

    return data;
}

void Binson::serialize(binson_writer *w) const
{
    binson_write_object_begin(w);
    seralizeItems(w);
    binson_write_object_end(w);
}

BinsonValue Binson::deseralizeItem(binson_parser *p)
{
    uint8_t t = binson_parser_get_type(p);
    switch(t)
    {
    case BINSON_ID_BOOLEAN:
        return BinsonValue(binson_parser_get_boolean(p) == 0 ? false : true);
        break;
    case BINSON_ID_INTEGER:
        return BinsonValue(binson_parser_get_integer(p));
        break;
    case BINSON_ID_DOUBLE:
        return BinsonValue(binson_parser_get_double(p));
        break;
    case BINSON_ID_STRING:
    {
        bbuf *buf;
        buf = binson_parser_get_string_bbuf(p);
        if (buf)
            return BinsonValue(string(reinterpret_cast<const char*>(buf->bptr), buf->bsize));
        else
            throw runtime_error("Parse error, missing string");
    }
        break;
    case BINSON_ID_BYTES:
    {
        bbuf *buf;
        buf = binson_parser_get_bytes_bbuf(p);
        if (buf)
            return BinsonValue(vector<uint8_t>(buf->bptr, buf->bptr + buf->bsize));
        else
            throw runtime_error("Parse error, missing data");
    }
        break;
    case BINSON_ID_OBJECT:
    {
        IF_RUNTIME_ERROR(binson_parser_go_into_object(p), "Parse error");
        Binson b;
        b.deseralizeItems(p);
        IF_RUNTIME_ERROR(binson_parser_leave_object(p), "Parse error");
        return BinsonValue(b);
    }
        break;
    case BINSON_ID_ARRAY:
    {
        IF_RUNTIME_ERROR(binson_parser_go_into_array(p), "Parse error");
        vector<BinsonValue> array;
        while(binson_parser_next(p))
        {
            array.push_back(deseralizeItem(p));
        }
        IF_RUNTIME_ERROR(binson_parser_leave_array(p), "Parse error");
        return array;
    }
        break;
    default:
        throw runtime_error("Unknown type");
    }
    return BinsonValue();
}

void Binson::deseralizeItems(binson_parser *p)
{
    while(binson_parser_next(p))
    {
        bbuf *buf;
        buf = binson_parser_get_name(p);
        IF_RUNTIME_ERROR(buf != nullptr, "Parse error");
        string name(reinterpret_cast<const char*>(buf->bptr), buf->bsize);
        put(name, deseralizeItem(p));
    }
}

void Binson::deserialize(const std::vector<uint8_t> &data)
{
    binson_parser p;
    clear();

    binson_parser_init(&p, const_cast<uint8_t*>(data.data()), data.size());
    binson_parser_go_into_object(&p);
    deseralizeItems(&p);
    binson_parser_leave_object(&p);
}

void Binson::deserialize(const uint8_t *data, size_t size)
{
    binson_parser p;
    clear();

    IF_RUNTIME_ERROR(binson_parser_init(&p, const_cast<uint8_t*>(data), size), "Parser init error");
    deserialize(&p);
}

void Binson::deserialize(binson_parser *p)
{
    clear();
    IF_RUNTIME_ERROR(binson_parser_reset(p), "Parser reset error");
    IF_RUNTIME_ERROR(binson_parser_go_into_object(p), "Parse error");
    deseralizeItems(p);
    IF_RUNTIME_ERROR(binson_parser_leave_object(p), "Parse error");
}

string Binson::toStr() const
{
    binson_parser p;
    string str;
    str.resize(10000);
    vector<uint8_t> stream = serialize();
    if (stream.empty())
        return string();
    int trys = 5;
    bool result = false;
    size_t size = 0;
    do
    {
        if (!binson_parser_init(&p, stream.data(), stream.size()))
            break;
        size = str.size();
        result = binson_parser_to_string(&p, (char*)str.data(), &size, true);
        if (!result)
            str.resize(size * 2);
    } while(!result && trys-- > 0 && p.error_flags == 0);

    if (!result)
        str.clear();
    else
        str.resize(size);
    return str;
}

BinsonValue::BinsonValue()
{

}

BinsonValue::BinsonValue(bool val)
{
    m_val.b = val;
    m_val.setType(Types::boolType);
}

BinsonValue::BinsonValue(int64_t val)
{
    m_val.i = val;
    m_val.setType(Types::intType);
}

BinsonValue::BinsonValue(int val)
{
    m_val.i = val;
    m_val.setType(Types::intType);
}

BinsonValue::BinsonValue(double val)
{
    m_val.d = val;
    m_val.setType(Types::doubleType);
}

BinsonValue::BinsonValue(string &&val)
{
    m_val.str = move(val);
    m_val.setType(Types::stringType);
}

BinsonValue::BinsonValue(const string &val)
{
    m_val.str = val;
    m_val.setType(Types::stringType);
}

BinsonValue::BinsonValue(const char *str)
{
    m_val.str = string(str);
    m_val.setType(Types::stringType);
}

BinsonValue::BinsonValue(std::vector<uint8_t> &&val)
{
    m_val.bin = move(val);
    m_val.setType(Types::binaryType);
}

BinsonValue::BinsonValue(const std::vector<uint8_t> &val)
{
    m_val.bin = val;
    m_val.setType(Types::binaryType);
}

BinsonValue::BinsonValue(Binson &&val)
{
    m_val.o = move(val);
    m_val.setType(Types::objectType);
}

BinsonValue::BinsonValue(const Binson &val)
{
    m_val.o = val;
    m_val.setType(Types::objectType);
}

BinsonValue::BinsonValue(std::vector<BinsonValue> &&val)
{
    m_val.a = move(val);
    m_val.setType(Types::arrayType);
}

BinsonValue::BinsonValue(const std::vector<BinsonValue> &val)
{
    m_val.a = val;
    m_val.setType(Types::arrayType);
}

BinsonValue BinsonValue::operator=(bool &&val)
{
    m_val.b = move(val);
    m_val.setType(Types::boolType);
    return *this;
}

BinsonValue BinsonValue::operator=(int64_t &&val)
{
    m_val.i = move(val);
    m_val.setType(Types::intType);
    return *this;
}

BinsonValue BinsonValue::operator=(int &&val)
{
    m_val.i = val;
    m_val.setType(Types::intType);
    return *this;
}

BinsonValue BinsonValue::operator=(double &&val)
{
    m_val.d = move(val);
    m_val.setType(Types::doubleType);
    return *this;
}

BinsonValue BinsonValue::operator=(string &&val)
{
    m_val.str = move(val);
    m_val.setType(Types::stringType);
    return *this;
}

BinsonValue BinsonValue::operator=(std::vector<uint8_t> &&val)
{
    m_val.bin = move(val);
    m_val.setType(Types::binaryType);
    return *this;
}

BinsonValue BinsonValue::operator=(Binson &&val)
{
    m_val.o = move(val);
    m_val.setType(Types::objectType);
    return *this;
}

BinsonValue BinsonValue::operator=(std::vector<BinsonValue> &&val)
{
    m_val.a = move(val);
    m_val.setType(Types::arrayType);
    return *this;
}
<commit_msg>Fixed some clang warnings<commit_after>#include "binson.hpp"

#include <binson_light.h>

#include <string.h>
#include <stdexcept>

using namespace std;

#define IF_RUNTIME_ERROR(x, msg) if (!(x)) throw std::runtime_error(msg)

const std::array<std::string, 8> BinsonValue::typeToString
{
    {
        "noneType",
        "boolType",
        "intType",
        "doubleType",
        "stringType",
        "binaryType",
        "objectType",
        "arrayType"
    }
};

Binson & Binson::put(const std::string &key, const BinsonValue &v)
{
    m_items[key] = move(v);
    return *this;
}

Binson & Binson::put(const std::string &key, Binson o)
{
    m_items[key] = BinsonValue(move(o));
    return *this;
}

Binson & Binson::put(const string &key, const uint8_t *data, size_t size)
{
    vector<uint8_t> v(data, data + size);
    m_items[key] = BinsonValue(v);
    return *this;
}

const BinsonValue Binson::get(const string &key) const
{
    if (!hasKey(key))
        throw std::out_of_range("Key '" + key + "' does not exist");
    else
        return m_items.at(key);
}

bool Binson::hasKey(const string &key) const
{
    return m_items.find(key) != m_items.end();
}

void Binson::clear()
{
    m_items.clear();
}

void Binson::seralizeItem(binson_writer *w, const BinsonValue &val) const
{
    switch(val.myType())
    {
    case BinsonValue::Types::noneType:
        break;
    case BinsonValue::Types::boolType:
        binson_write_boolean(w, val.getBool());
        break;
    case BinsonValue::Types::intType:
        binson_write_integer(w, val.getInt());
        break;
    case BinsonValue::Types::doubleType:
        binson_write_double(w, val.getDouble());
        break;
    case BinsonValue::Types::stringType:
        binson_write_string_with_len(w,
                                     val.getString().data(),
                                     val.getString().size());
        break;
    case BinsonValue::Types::binaryType:
        binson_write_bytes(w, val.getBin().data(), val.getBin().size());
        break;
    case BinsonValue::Types::objectType:
        binson_write_object_begin(w);
        val.getObject().seralizeItems(w);
        binson_write_object_end(w);
        break;
    case BinsonValue::Types::arrayType:
        binson_write_array_begin(w);
        for (auto &arrayValue : val.getArray())
        {
            seralizeItem(w, arrayValue);
        }
        binson_write_array_end(w);
        break;
    default:
        throw runtime_error("Unknown binson type");
    }
}

void Binson::seralizeItems(binson_writer *w) const
{
    for (auto &item: m_items)
    {
        binson_write_name_with_len(w, item.first.c_str(), item.first.size());
        seralizeItem(w, item.second);
    }
}

std::vector<uint8_t> Binson::serialize() const
{
    vector<uint8_t> data;
    data.resize(1000);
    binson_writer w;
    binson_writer_init(&w, data.data(), data.size());
    serialize(&w);
    if (w.error_flags == BINSON_ERROR_RANGE)
    {
        data.resize(binson_writer_get_counter(&w));
        binson_writer_init(&w, data.data(), data.size());
        serialize(&w);
    }

    if (w.error_flags == BINSON_ERROR_NONE)
        data.resize(binson_writer_get_counter(&w));
    else
        data.clear();

    return data;
}

void Binson::serialize(binson_writer *w) const
{
    binson_write_object_begin(w);
    seralizeItems(w);
    binson_write_object_end(w);
}

BinsonValue Binson::deseralizeItem(binson_parser *p)
{
    uint8_t t = binson_parser_get_type(p);
    switch(t)
    {
    case BINSON_ID_BOOLEAN:
        return BinsonValue(binson_parser_get_boolean(p) == 0 ? false : true);
        break;
    case BINSON_ID_INTEGER:
        return BinsonValue(binson_parser_get_integer(p));
        break;
    case BINSON_ID_DOUBLE:
        return BinsonValue(binson_parser_get_double(p));
        break;
    case BINSON_ID_STRING:
    {
        bbuf *buf;
        buf = binson_parser_get_string_bbuf(p);
        if (buf)
            return BinsonValue(string(reinterpret_cast<const char*>(buf->bptr), buf->bsize));
        else
            throw runtime_error("Parse error, missing string");
    }
        break;
    case BINSON_ID_BYTES:
    {
        bbuf *buf;
        buf = binson_parser_get_bytes_bbuf(p);
        if (buf)
            return BinsonValue(vector<uint8_t>(buf->bptr, buf->bptr + buf->bsize));
        else
            throw runtime_error("Parse error, missing data");
    }
        break;
    case BINSON_ID_OBJECT:
    {
        IF_RUNTIME_ERROR(binson_parser_go_into_object(p), "Parse error");
        Binson b;
        b.deseralizeItems(p);
        IF_RUNTIME_ERROR(binson_parser_leave_object(p), "Parse error");
        return BinsonValue(b);
    }
        break;
    case BINSON_ID_ARRAY:
    {
        IF_RUNTIME_ERROR(binson_parser_go_into_array(p), "Parse error");
        vector<BinsonValue> array;
        while(binson_parser_next(p))
        {
            array.push_back(deseralizeItem(p));
        }
        IF_RUNTIME_ERROR(binson_parser_leave_array(p), "Parse error");
        return array;
    }
        break;
    default:
        throw runtime_error("Unknown type");
    }
    return BinsonValue();
}

void Binson::deseralizeItems(binson_parser *p)
{
    while(binson_parser_next(p))
    {
        bbuf *buf;
        buf = binson_parser_get_name(p);
        IF_RUNTIME_ERROR(buf != nullptr, "Parse error");
        string name(reinterpret_cast<const char*>(buf->bptr), buf->bsize);
        put(name, deseralizeItem(p));
    }
}

void Binson::deserialize(const std::vector<uint8_t> &data)
{
    binson_parser p;
    clear();

    binson_parser_init(&p, const_cast<uint8_t*>(data.data()), data.size());
    binson_parser_go_into_object(&p);
    deseralizeItems(&p);
    binson_parser_leave_object(&p);
}

void Binson::deserialize(const uint8_t *data, size_t size)
{
    binson_parser p;
    clear();

    IF_RUNTIME_ERROR(binson_parser_init(&p, const_cast<uint8_t*>(data), size), "Parser init error");
    deserialize(&p);
}

void Binson::deserialize(binson_parser *p)
{
    clear();
    IF_RUNTIME_ERROR(binson_parser_reset(p), "Parser reset error");
    IF_RUNTIME_ERROR(binson_parser_go_into_object(p), "Parse error");
    deseralizeItems(p);
    IF_RUNTIME_ERROR(binson_parser_leave_object(p), "Parse error");
}

string Binson::toStr() const
{
    binson_parser p;
    string str;
    str.resize(10000);
    vector<uint8_t> stream = serialize();
    if (stream.empty())
        return string();
    int trys = 5;
    bool result = false;
    size_t size = 0;
    do
    {
        if (!binson_parser_init(&p, stream.data(), stream.size()))
            break;
        size = str.size();
        result = binson_parser_to_string(&p, (char*)str.data(), &size, true);
        if (!result)
            str.resize(size * 2);
    } while(!result && trys-- > 0 && p.error_flags == 0);

    if (!result)
        str.clear();
    else
        str.resize(size);
    return str;
}

BinsonValue::BinsonValue()
{

}

BinsonValue::BinsonValue(bool val)
{
    m_val.b = val;
    m_val.setType(Types::boolType);
}

BinsonValue::BinsonValue(int64_t val)
{
    m_val.i = val;
    m_val.setType(Types::intType);
}

BinsonValue::BinsonValue(int val)
{
    m_val.i = val;
    m_val.setType(Types::intType);
}

BinsonValue::BinsonValue(double val)
{
    m_val.d = val;
    m_val.setType(Types::doubleType);
}

BinsonValue::BinsonValue(string &&val)
{
    m_val.str = move(val);
    m_val.setType(Types::stringType);
}

BinsonValue::BinsonValue(const string &val)
{
    m_val.str = val;
    m_val.setType(Types::stringType);
}

BinsonValue::BinsonValue(const char *str)
{
    m_val.str = string(str);
    m_val.setType(Types::stringType);
}

BinsonValue::BinsonValue(std::vector<uint8_t> &&val)
{
    m_val.bin = move(val);
    m_val.setType(Types::binaryType);
}

BinsonValue::BinsonValue(const std::vector<uint8_t> &val)
{
    m_val.bin = val;
    m_val.setType(Types::binaryType);
}

BinsonValue::BinsonValue(Binson &&val)
{
    m_val.o = move(val);
    m_val.setType(Types::objectType);
}

BinsonValue::BinsonValue(const Binson &val)
{
    m_val.o = val;
    m_val.setType(Types::objectType);
}

BinsonValue::BinsonValue(std::vector<BinsonValue> &&val)
{
    m_val.a = move(val);
    m_val.setType(Types::arrayType);
}

BinsonValue::BinsonValue(const std::vector<BinsonValue> &val)
{
    m_val.a = val;
    m_val.setType(Types::arrayType);
}

BinsonValue BinsonValue::operator=(bool &&val)
{
    m_val.b = move(val);
    m_val.setType(Types::boolType);
    return *this;
}

BinsonValue BinsonValue::operator=(int64_t &&val)
{
    m_val.i = move(val);
    m_val.setType(Types::intType);
    return *this;
}

BinsonValue BinsonValue::operator=(int &&val)
{
    m_val.i = val;
    m_val.setType(Types::intType);
    return *this;
}

BinsonValue BinsonValue::operator=(double &&val)
{
    m_val.d = move(val);
    m_val.setType(Types::doubleType);
    return *this;
}

BinsonValue BinsonValue::operator=(string &&val)
{
    m_val.str = move(val);
    m_val.setType(Types::stringType);
    return *this;
}

BinsonValue BinsonValue::operator=(std::vector<uint8_t> &&val)
{
    m_val.bin = move(val);
    m_val.setType(Types::binaryType);
    return *this;
}

BinsonValue BinsonValue::operator=(Binson &&val)
{
    m_val.o = move(val);
    m_val.setType(Types::objectType);
    return *this;
}

BinsonValue BinsonValue::operator=(std::vector<BinsonValue> &&val)
{
    m_val.a = move(val);
    m_val.setType(Types::arrayType);
    return *this;
}
<|endoftext|>


<commit_before>#ifndef HONDO_SIMPLESHADER_HPP
#define HONDO_SIMPLESHADER_HPP
class SkyShader;
#include "ShaderProgram.hpp"
#define GLM_FORCE_RADIANS
#include <glm/glm.hpp>
class SkyShader {
  private:
    ShaderProgram shader_program;
    const GLuint mvpMatID;
    const GLuint modelMatID;
  public:
    SkyShader();
    void operator()();
    void stop();
    void set_mvp_mat(const glm::mat4& mvpMat);
    void set_model_mat(const glm::mat4& mvpMat);
};
#endif
<commit_msg>Fixed include guard of SkyShader<commit_after>#ifndef HONDO_SKYSHADER_HPP
#define HONDO_SKYSHADER_HPP
class SkyShader;
#include "ShaderProgram.hpp"
#define GLM_FORCE_RADIANS
#include <glm/glm.hpp>
class SkyShader {
  private:
    ShaderProgram shader_program;
    const GLuint mvpMatID;
    const GLuint modelMatID;
  public:
    SkyShader();
    void operator()();
    void stop();
    void set_mvp_mat(const glm::mat4& mvpMat);
    void set_model_mat(const glm::mat4& mvpMat);
};
#endif
<|endoftext|>


<commit_before>/**
 * Zillians MMO
 * Copyright (C) 2007-2009 Zillians.com, Inc.
 * For more information see http://www.zillians.com
 *
 * Zillians MMO is the library and runtime for massive multiplayer online game
 * development in utility computing model, which runs as a service for every
 * developer to build their virtual world running on our GPU-assisted machines.
 *
 * This is a close source library intended to be used solely within Zillians.com
 *
 * 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
 * COPYRIGHT HOLDER(S) 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.
 */
/**
 * @date Aug 28, 2009 sdk - Initial version created.
 */

#include "core-api/ContextHub.h"

namespace zillians {

#if !ZILLIANS_SERVICEHUB_ALLOW_ARBITRARY_CONTEXT_PLACEMENT_FOR_DIFFERENT_INSTANCE
tbb::atomic<uint32> ContextHub::msContextIndexer;
#endif

}
<commit_msg>	deleted:    src/libzillians-common-core-api/ContextHub.cpp<commit_after><|endoftext|>


<commit_before>/* Copyright © 2001-2014, Canal TP and/or its affiliates. All rights reserved.

This file is part of Navitia,
    the software to build cool stuff with public transport.

Hope you'll enjoy and contribute to this project,
    powered by Canal TP (www.canaltp.fr).
Help us simplify mobility and open public transport:
    a non ending quest to the responsive locomotion way of traveling!

LICENCE: 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
(at your option) 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/>.

Stay tuned using
twitter @navitia
IRC #navitia on freenode
https://groups.google.com/d/forum/navitia
www.navitia.io
*/

#include "raptor_solutions.h"
#include "raptor_path.h"
#include "raptor.h"
#include "raptor_path_defs.h"

namespace bt = boost::posix_time;
namespace navitia { namespace routing {

Solutions
get_solutions(const std::vector<std::pair<type::idx_t, navitia::time_duration> > &departs,
             const std::vector<std::pair<type::idx_t, navitia::time_duration> > &destinations,
             bool clockwise, const type::AccessibiliteParams & accessibilite_params,
             bool disruption_active, const RAPTOR& raptor) {
      Solutions result;
      auto pareto_front = get_pareto_front(clockwise, departs, destinations,
              accessibilite_params, disruption_active, raptor);
      result.insert(pareto_front.begin(), pareto_front.end());

      if(!pareto_front.empty()) {
          auto walking_solutions = get_walking_solutions(clockwise, departs, destinations,
                  *pareto_front.rbegin(), disruption_active, accessibilite_params, raptor);
          if(!walking_solutions.empty()) {
            result.insert(walking_solutions.begin(), walking_solutions.end());
          }
      }
      return result;
}

Solutions
get_solutions(const std::vector<std::pair<type::idx_t, navitia::time_duration> > &departs,
              const DateTime &dep, bool clockwise, const type::Data & data, bool) {
    Solutions result;
    for(auto dep_dist : departs) {
        for(auto journey_pattern : data.pt_data->stop_points[dep_dist.first]->journey_pattern_point_list) {
            Solution d;
            d.count = 0;
            d.jpp_idx = journey_pattern->idx;
            d.walking_time = dep_dist.second;
            if(clockwise)
                d.arrival = dep + d.walking_time.total_seconds();
            else
                d.arrival = dep - d.walking_time.total_seconds();
            result.insert(d);
        }
    }
    return result;
}

// Does the current date improves compared to best_so_far – we must not forget to take the walking duration
bool improves(const DateTime & best_so_far, bool clockwise, const DateTime & current, int walking_duration) {
    if(clockwise) {
        return (current - walking_duration) > best_so_far;
    } else {
        return (current + walking_duration) < best_so_far;
    }
}

Solutions
get_pareto_front(bool clockwise, const std::vector<std::pair<type::idx_t, navitia::time_duration> > &departs,
               const std::vector<std::pair<type::idx_t, navitia::time_duration> > &destinations,
               const type::AccessibiliteParams & accessibilite_params, bool disruption_active, const RAPTOR& raptor) {
    Solutions result;

    DateTime best_dt, best_dt_jpp;
    if(clockwise) {
        best_dt = DateTimeUtils::min;
        best_dt_jpp = DateTimeUtils::min;
    } else {
        best_dt = DateTimeUtils::inf;
        best_dt_jpp = DateTimeUtils::inf;
    }
    for(unsigned int round=1; round <= raptor.count; ++round) {
        // For every round with look for the best journey pattern point that belongs to one of the destination stop points
        // We must not forget to walking duration
        type::idx_t best_jpp = type::invalid_idx;
        for(auto spid_dist : destinations) {
            for(auto journey_pattern_point : raptor.data.pt_data->stop_points[spid_dist.first]->journey_pattern_point_list) {
                type::idx_t jppidx = journey_pattern_point->idx;
                auto& l = raptor.labels[round][jppidx];
                if(l.pt_is_initialized() &&
                   improves(best_dt, clockwise, l.dt_pt, spid_dist.second.total_seconds()) ) {
                    best_jpp = jppidx;
                    best_dt_jpp = l.dt_pt;
                    // Dans le sens horaire : lors du calcul on gardé que l’heure de départ, mais on veut l’arrivée
                    // Il faut donc retrouver le stop_time qui nous intéresse avec best_stop_time
                    const type::StopTime* st;
                    DateTime dt = 0;

                    std::tie(st, dt) = best_stop_time(journey_pattern_point, l.dt_pt, accessibilite_params.vehicle_properties,
                                                      !clockwise, disruption_active, raptor.data, true);
                    BOOST_ASSERT(st);
                    if(st != nullptr) {
                        if(clockwise) {
                            auto arrival_time = !st->is_frequency() ? st->arrival_time : st->f_arrival_time(DateTimeUtils::hour(dt));
                            DateTimeUtils::update(best_dt_jpp, arrival_time, false);
                        } else {
                            auto departure_time = !st->is_frequency() ? st->departure_time : st->f_departure_time(DateTimeUtils::hour(dt));
                            DateTimeUtils::update(best_dt_jpp, departure_time, true);
                        }
                    }
                    if(clockwise)
                        best_dt = l.dt_pt - spid_dist.second.total_seconds();
                    else
                        best_dt = l.dt_pt + spid_dist.second.total_seconds();
                }
            }
        }
        if(best_jpp != type::invalid_idx) {
            Solution s;
            s.jpp_idx = best_jpp;
            s.count = round;
            s.walking_time = getWalkingTime(round, best_jpp, departs, destinations, clockwise, disruption_active,
                                            accessibilite_params, raptor);
            s.arrival = best_dt_jpp;
            s.ratio = 0;
            type::idx_t final_jpp_idx;
            std::tie(final_jpp_idx, s.upper_bound) = get_final_jppidx_and_date(round, best_jpp, clockwise,
                                                                             disruption_active, accessibilite_params, raptor);
            for(auto spid_dep : departs) {
                if(raptor.data.pt_data->journey_pattern_points[final_jpp_idx]->stop_point->idx == spid_dep.first) {
                    if(clockwise) {
                        s.upper_bound = s.upper_bound + spid_dep.second.total_seconds();
                        s.total_arrival = raptor.labels[round][best_jpp].dt_pt - spid_dep.second.total_seconds();
                    }else {
                        s.upper_bound = s.upper_bound - spid_dep.second.total_seconds();
                        s.total_arrival = raptor.labels[round][best_jpp].dt_pt + spid_dep.second.total_seconds();
                    }
                }
            }
            result.insert(s);
        }
    }

    return result;
}

Solutions
get_walking_solutions(bool clockwise, const std::vector<std::pair<type::idx_t, navitia::time_duration> > &departs,
                      const std::vector<std::pair<type::idx_t, navitia::time_duration> > &destinations, const Solution& best,
                      const bool disruption_active, const type::AccessibiliteParams &accessibilite_params,
                      const RAPTOR& raptor) {
    Solutions result;

    std::/*unordered_*/map<type::idx_t, Solution> tmp;
    // We start at 1 because we don't want results of the first round
    for(uint32_t i=1; i <= raptor.count; ++i) {
        for(auto spid_dist : destinations) {
            Solution best_departure;
            best_departure.ratio = 2;
            best_departure.jpp_idx = type::invalid_idx;
            for(auto journey_pattern_point : raptor.data.pt_data->stop_points[spid_dist.first]->journey_pattern_point_list) {
                type::idx_t jppidx = journey_pattern_point->idx;
                // We only want solution ending by a vehicle journey or a stay_in
                if(raptor.labels[i][journey_pattern_point->idx].pt_is_initialized()) {
                    navitia::time_duration walking_time = getWalkingTime(i, jppidx, departs, destinations, clockwise,
                                                                         disruption_active, accessibilite_params, raptor);
                    if(best.walking_time < walking_time) {
                        continue;
                    }
                    float lost_time;
                    if(clockwise)
                        lost_time = best.total_arrival -
                                    (raptor.labels[i][jppidx].dt_pt - best.walking_time.total_seconds());
                    else
                        lost_time = (raptor.labels[i][jppidx].dt_pt + spid_dist.second.total_seconds()) -
                                best.total_arrival;

                    //Si je gagne 5 minutes de marche a pied, je suis pret à perdre jusqu'à 10 minutes.
                    int walking_time_diff_in_s = (best.walking_time - walking_time).total_seconds();
                    if (walking_time_diff_in_s > 0) {
                        float ratio = lost_time / walking_time_diff_in_s;
                        if( ratio >= best_departure.ratio) {
                            continue;
                        }
                        Solution s;
                            s.jpp_idx = jppidx;
                        s.count = i;
                        s.ratio = ratio;
                        s.walking_time = walking_time;
                        s.arrival = raptor.labels[i][jppidx].dt_pt;
                        type::idx_t final_jpp_idx;
                        DateTime last_time;
                        std::tie(final_jpp_idx, last_time) = get_final_jppidx_and_date(i, jppidx, clockwise,
                                            disruption_active, accessibilite_params, raptor);

                        if(clockwise) {
                            s.upper_bound = last_time;
                            for(auto spid_dep : departs) {
                                if(raptor.data.pt_data->journey_pattern_points[final_jpp_idx]->stop_point->idx == spid_dep.first) {
                                    s.upper_bound = s.upper_bound + (spid_dep.second.total_seconds());
                                }
                            }
                        } else {
                            s.upper_bound = last_time;
                            for(auto spid_dep : departs) {
                                if(raptor.data.pt_data->journey_pattern_points[final_jpp_idx]->stop_point->idx == spid_dep.first) {
                                    s.upper_bound = s.upper_bound - (spid_dep.second.total_seconds());
                                }
                            }
                        }
                        best_departure = s;
                    }
                }
            }
            if(best_departure.jpp_idx != type::invalid_idx) {
                if(tmp.find(best_departure.jpp_idx) == tmp.end()) {
                    tmp.insert(std::make_pair(best_departure.jpp_idx, best_departure));
                } else if(tmp[best_departure.jpp_idx].ratio > best_departure.ratio) {
                    tmp[best_departure.jpp_idx] = best_departure;
                }
            }
        }
    }

    std::vector<Solution> to_sort;
    for(auto p : tmp) {
        to_sort.push_back(p.second);
    }
    std::sort(to_sort.begin(), to_sort.end(),
            [](const Solution s1, const Solution s2) { return s1.ratio < s2.ratio;});

    if(to_sort.size() > 2)
        to_sort.resize(2);
    result.insert(to_sort.begin(), to_sort.end());

    return result;
}

struct VisitorFinalJppAndDate : public BasePathVisitor {
    type::idx_t current_jpp = type::invalid_idx;
    DateTime last_time = DateTimeUtils::inf;
    void final_step(const type::idx_t current_jpp, size_t count, const std::vector<label_vector_t> &labels) {
        this->current_jpp = current_jpp;
        last_time = labels[count][current_jpp].dt_pt;
    }
};

// Reparcours l’itinéraire rapidement pour avoir le JPP et la date de départ (si on cherchait l’arrivée au plus tôt)
std::pair<type::idx_t, DateTime>
get_final_jppidx_and_date(int count, type::idx_t jpp_idx, bool clockwise, bool disruption_active,
                          const type::AccessibiliteParams & accessibilite_params, const RAPTOR& raptor) {
    VisitorFinalJppAndDate v;
    read_path(v, jpp_idx, count, !clockwise, disruption_active, accessibilite_params, raptor);
    return std::make_pair(v.current_jpp, v.last_time);
}

struct VisitorWalkingTime : public BasePathVisitor {
    navitia::time_duration walking_time = {};
    type::idx_t departure_jpp_idx = type::invalid_idx;
    void connection(type::StopPoint* , type::StopPoint* ,
                boost::posix_time::ptime dep_time, boost::posix_time::ptime arr_time,
                type::StopPointConnection*) {

        walking_time += navitia::seconds((arr_time - dep_time).total_seconds());
    }

    void final_step(type::idx_t current_jpp, size_t , const std::vector<std::vector<Label>> &){
        departure_jpp_idx = current_jpp;
    }

};

navitia::time_duration getWalkingTime(int count, type::idx_t jpp_idx, const std::vector<std::pair<type::idx_t, navitia::time_duration> > &departs,
                     const std::vector<std::pair<type::idx_t, navitia::time_duration> > &destinations,
                     bool clockwise, bool disruption_active, const type::AccessibiliteParams & accessibilite_params,
                     const RAPTOR& raptor) {

    const auto* current_jpp = raptor.data.pt_data->journey_pattern_points[jpp_idx];
    navitia::time_duration walking_time = {};

    //Marche à la fin
    for(auto dest_dist : destinations) {
        if(dest_dist.first == current_jpp->stop_point->idx) {
            walking_time = dest_dist.second;
            break;
        }
    }

    VisitorWalkingTime v;
    read_path(v, current_jpp->idx, count, !clockwise, disruption_active, accessibilite_params, raptor);
    walking_time += v.walking_time;
    if (v.departure_jpp_idx == type::invalid_idx) {
        return walking_time;
    }
    const auto* departure_jpp = raptor.data.pt_data->journey_pattern_points[v.departure_jpp_idx];
    //Marche au départ
    for(auto dep_dist : departs) {
        if(dep_dist.first == departure_jpp->stop_point->idx) {
            walking_time += dep_dist.second;
            break;
        }
    }

    return walking_time;
}

}}

<commit_msg>Kraken: fix total arrival in get_pareto_front<commit_after>/* Copyright © 2001-2014, Canal TP and/or its affiliates. All rights reserved.

This file is part of Navitia,
    the software to build cool stuff with public transport.

Hope you'll enjoy and contribute to this project,
    powered by Canal TP (www.canaltp.fr).
Help us simplify mobility and open public transport:
    a non ending quest to the responsive locomotion way of traveling!

LICENCE: 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
(at your option) 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/>.

Stay tuned using
twitter @navitia
IRC #navitia on freenode
https://groups.google.com/d/forum/navitia
www.navitia.io
*/

#include "raptor_solutions.h"
#include "raptor_path.h"
#include "raptor.h"
#include "raptor_path_defs.h"

namespace bt = boost::posix_time;
namespace navitia { namespace routing {

Solutions
get_solutions(const std::vector<std::pair<type::idx_t, navitia::time_duration> > &departs,
             const std::vector<std::pair<type::idx_t, navitia::time_duration> > &destinations,
             bool clockwise, const type::AccessibiliteParams & accessibilite_params,
             bool disruption_active, const RAPTOR& raptor) {
      Solutions result;
      auto pareto_front = get_pareto_front(clockwise, departs, destinations,
              accessibilite_params, disruption_active, raptor);
      result.insert(pareto_front.begin(), pareto_front.end());

      if(!pareto_front.empty()) {
          auto walking_solutions = get_walking_solutions(clockwise, departs, destinations,
                  *pareto_front.rbegin(), disruption_active, accessibilite_params, raptor);
          if(!walking_solutions.empty()) {
            result.insert(walking_solutions.begin(), walking_solutions.end());
          }
      }
      return result;
}

Solutions
get_solutions(const std::vector<std::pair<type::idx_t, navitia::time_duration> > &departs,
              const DateTime &dep, bool clockwise, const type::Data & data, bool) {
    Solutions result;
    for(auto dep_dist : departs) {
        for(auto journey_pattern : data.pt_data->stop_points[dep_dist.first]->journey_pattern_point_list) {
            Solution d;
            d.count = 0;
            d.jpp_idx = journey_pattern->idx;
            d.walking_time = dep_dist.second;
            if(clockwise)
                d.arrival = dep + d.walking_time.total_seconds();
            else
                d.arrival = dep - d.walking_time.total_seconds();
            result.insert(d);
        }
    }
    return result;
}

// Does the current date improves compared to best_so_far – we must not forget to take the walking duration
bool improves(const DateTime & best_so_far, bool clockwise, const DateTime & current, int walking_duration) {
    if(clockwise) {
        return (current - walking_duration) > best_so_far;
    } else {
        return (current + walking_duration) < best_so_far;
    }
}

Solutions
get_pareto_front(bool clockwise, const std::vector<std::pair<type::idx_t, navitia::time_duration> > &departs,
               const std::vector<std::pair<type::idx_t, navitia::time_duration> > &destinations,
               const type::AccessibiliteParams & accessibilite_params, bool disruption_active, const RAPTOR& raptor) {
    Solutions result;

    DateTime best_dt, best_dt_jpp;
    if(clockwise) {
        best_dt = DateTimeUtils::min;
        best_dt_jpp = DateTimeUtils::min;
    } else {
        best_dt = DateTimeUtils::inf;
        best_dt_jpp = DateTimeUtils::inf;
    }
    for(unsigned int round=1; round <= raptor.count; ++round) {
        // For every round with look for the best journey pattern point that belongs to one of the destination stop points
        // We must not forget to walking duration
        type::idx_t best_jpp = type::invalid_idx;
        for(auto spid_dist : destinations) {
            for(auto journey_pattern_point : raptor.data.pt_data->stop_points[spid_dist.first]->journey_pattern_point_list) {
                type::idx_t jppidx = journey_pattern_point->idx;
                auto& l = raptor.labels[round][jppidx];
                if(l.pt_is_initialized() &&
                   improves(best_dt, clockwise, l.dt_pt, spid_dist.second.total_seconds()) ) {
                    best_jpp = jppidx;
                    best_dt_jpp = l.dt_pt;
                    // Dans le sens horaire : lors du calcul on gardé que l’heure de départ, mais on veut l’arrivée
                    // Il faut donc retrouver le stop_time qui nous intéresse avec best_stop_time
                    const type::StopTime* st;
                    DateTime dt = 0;

                    std::tie(st, dt) = best_stop_time(journey_pattern_point, l.dt_pt, accessibilite_params.vehicle_properties,
                                                      !clockwise, disruption_active, raptor.data, true);
                    BOOST_ASSERT(st);
                    if(st != nullptr) {
                        if(clockwise) {
                            auto arrival_time = !st->is_frequency() ? st->arrival_time : st->f_arrival_time(DateTimeUtils::hour(dt));
                            DateTimeUtils::update(best_dt_jpp, arrival_time, false);
                        } else {
                            auto departure_time = !st->is_frequency() ? st->departure_time : st->f_departure_time(DateTimeUtils::hour(dt));
                            DateTimeUtils::update(best_dt_jpp, departure_time, true);
                        }
                    }
                    if(clockwise)
                        best_dt = l.dt_pt - spid_dist.second.total_seconds();
                    else
                        best_dt = l.dt_pt + spid_dist.second.total_seconds();
                }
            }
        }
        if(best_jpp != type::invalid_idx) {
            Solution s;
            s.jpp_idx = best_jpp;
            s.count = round;
            s.walking_time = getWalkingTime(round, best_jpp, departs, destinations, clockwise, disruption_active,
                                            accessibilite_params, raptor);
            s.arrival = best_dt_jpp;
            s.ratio = 0;
            s.total_arrival = best_dt;
            type::idx_t final_jpp_idx;
            std::tie(final_jpp_idx, s.upper_bound) = get_final_jppidx_and_date(round, best_jpp, clockwise,
                                                                             disruption_active, accessibilite_params, raptor);
            for(auto spid_dep : departs) {
                if(raptor.data.pt_data->journey_pattern_points[final_jpp_idx]->stop_point->idx == spid_dep.first) {
                    if(clockwise) {
                        s.upper_bound = s.upper_bound + spid_dep.second.total_seconds();
                    }else {
                        s.upper_bound = s.upper_bound - spid_dep.second.total_seconds();
                    }
                }
            }
            result.insert(s);
        }
    }

    return result;
}

Solutions
get_walking_solutions(bool clockwise, const std::vector<std::pair<type::idx_t, navitia::time_duration> > &departs,
                      const std::vector<std::pair<type::idx_t, navitia::time_duration> > &destinations, const Solution& best,
                      const bool disruption_active, const type::AccessibiliteParams &accessibilite_params,
                      const RAPTOR& raptor) {
    Solutions result;

    std::/*unordered_*/map<type::idx_t, Solution> tmp;
    // We start at 1 because we don't want results of the first round
    for(uint32_t i=1; i <= raptor.count; ++i) {
        for(auto spid_dist : destinations) {
            Solution best_departure;
            best_departure.ratio = 2;
            best_departure.jpp_idx = type::invalid_idx;
            for(auto journey_pattern_point : raptor.data.pt_data->stop_points[spid_dist.first]->journey_pattern_point_list) {
                type::idx_t jppidx = journey_pattern_point->idx;
                // We only want solution ending by a vehicle journey or a stay_in
                if(raptor.labels[i][journey_pattern_point->idx].pt_is_initialized()) {
                    navitia::time_duration walking_time = getWalkingTime(i, jppidx, departs, destinations, clockwise,
                                                                         disruption_active, accessibilite_params, raptor);
                    if(best.walking_time < walking_time) {
                        continue;
                    }
                    float lost_time;
                    if(clockwise)
                        lost_time = best.total_arrival -
                                    (raptor.labels[i][jppidx].dt_pt - best.walking_time.total_seconds());
                    else
                        lost_time = (raptor.labels[i][jppidx].dt_pt + spid_dist.second.total_seconds()) -
                                best.total_arrival;

                    //Si je gagne 5 minutes de marche a pied, je suis pret à perdre jusqu'à 10 minutes.
                    int walking_time_diff_in_s = (best.walking_time - walking_time).total_seconds();
                    if (walking_time_diff_in_s > 0) {
                        float ratio = lost_time / walking_time_diff_in_s;
                        if( ratio >= best_departure.ratio) {
                            continue;
                        }
                        Solution s;
                            s.jpp_idx = jppidx;
                        s.count = i;
                        s.ratio = ratio;
                        s.walking_time = walking_time;
                        s.arrival = raptor.labels[i][jppidx].dt_pt;
                        type::idx_t final_jpp_idx;
                        DateTime last_time;
                        std::tie(final_jpp_idx, last_time) = get_final_jppidx_and_date(i, jppidx, clockwise,
                                            disruption_active, accessibilite_params, raptor);

                        if(clockwise) {
                            s.upper_bound = last_time;
                            for(auto spid_dep : departs) {
                                if(raptor.data.pt_data->journey_pattern_points[final_jpp_idx]->stop_point->idx == spid_dep.first) {
                                    s.upper_bound = s.upper_bound + (spid_dep.second.total_seconds());
                                }
                            }
                        } else {
                            s.upper_bound = last_time;
                            for(auto spid_dep : departs) {
                                if(raptor.data.pt_data->journey_pattern_points[final_jpp_idx]->stop_point->idx == spid_dep.first) {
                                    s.upper_bound = s.upper_bound - (spid_dep.second.total_seconds());
                                }
                            }
                        }
                        best_departure = s;
                    }
                }
            }
            if(best_departure.jpp_idx != type::invalid_idx) {
                if(tmp.find(best_departure.jpp_idx) == tmp.end()) {
                    tmp.insert(std::make_pair(best_departure.jpp_idx, best_departure));
                } else if(tmp[best_departure.jpp_idx].ratio > best_departure.ratio) {
                    tmp[best_departure.jpp_idx] = best_departure;
                }
            }
        }
    }

    std::vector<Solution> to_sort;
    for(auto p : tmp) {
        to_sort.push_back(p.second);
    }
    std::sort(to_sort.begin(), to_sort.end(),
            [](const Solution s1, const Solution s2) { return s1.ratio < s2.ratio;});

    if(to_sort.size() > 2)
        to_sort.resize(2);
    result.insert(to_sort.begin(), to_sort.end());

    return result;
}

struct VisitorFinalJppAndDate : public BasePathVisitor {
    type::idx_t current_jpp = type::invalid_idx;
    DateTime last_time = DateTimeUtils::inf;
    void final_step(const type::idx_t current_jpp, size_t count, const std::vector<label_vector_t> &labels) {
        this->current_jpp = current_jpp;
        last_time = labels[count][current_jpp].dt_pt;
    }
};

// Reparcours l’itinéraire rapidement pour avoir le JPP et la date de départ (si on cherchait l’arrivée au plus tôt)
std::pair<type::idx_t, DateTime>
get_final_jppidx_and_date(int count, type::idx_t jpp_idx, bool clockwise, bool disruption_active,
                          const type::AccessibiliteParams & accessibilite_params, const RAPTOR& raptor) {
    VisitorFinalJppAndDate v;
    read_path(v, jpp_idx, count, !clockwise, disruption_active, accessibilite_params, raptor);
    return std::make_pair(v.current_jpp, v.last_time);
}

struct VisitorWalkingTime : public BasePathVisitor {
    navitia::time_duration walking_time = {};
    type::idx_t departure_jpp_idx = type::invalid_idx;
    void connection(type::StopPoint* , type::StopPoint* ,
                boost::posix_time::ptime dep_time, boost::posix_time::ptime arr_time,
                type::StopPointConnection*) {

        walking_time += navitia::seconds((arr_time - dep_time).total_seconds());
    }

    void final_step(type::idx_t current_jpp, size_t , const std::vector<std::vector<Label>> &){
        departure_jpp_idx = current_jpp;
    }

};

navitia::time_duration getWalkingTime(int count, type::idx_t jpp_idx, const std::vector<std::pair<type::idx_t, navitia::time_duration> > &departs,
                     const std::vector<std::pair<type::idx_t, navitia::time_duration> > &destinations,
                     bool clockwise, bool disruption_active, const type::AccessibiliteParams & accessibilite_params,
                     const RAPTOR& raptor) {

    const auto* current_jpp = raptor.data.pt_data->journey_pattern_points[jpp_idx];
    navitia::time_duration walking_time = {};

    //Marche à la fin
    for(auto dest_dist : destinations) {
        if(dest_dist.first == current_jpp->stop_point->idx) {
            walking_time = dest_dist.second;
            break;
        }
    }

    VisitorWalkingTime v;
    read_path(v, current_jpp->idx, count, !clockwise, disruption_active, accessibilite_params, raptor);
    walking_time += v.walking_time;
    if (v.departure_jpp_idx == type::invalid_idx) {
        return walking_time;
    }
    const auto* departure_jpp = raptor.data.pt_data->journey_pattern_points[v.departure_jpp_idx];
    //Marche au départ
    for(auto dep_dist : departs) {
        if(dep_dist.first == departure_jpp->stop_point->idx) {
            walking_time += dep_dist.second;
            break;
        }
    }

    return walking_time;
}

}}

<|endoftext|>


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

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

// appleseed.renderer headers.
#include "renderer/modeling/material/material.h"

// appleseed.foundation headers.
#include "foundation/utility/api/specializedapiarrays.h"
#include "foundation/utility/containers/dictionary.h"

using namespace foundation;

namespace renderer
{

namespace
{
    //
    // Generic material.
    //

    const char* Model = "generic_material";

    class GenericMaterial
      : public Material
    {
      public:
        GenericMaterial(
            const char*             name,
            const ParamArray&       params)
          : Material(name, params)
        {
            m_inputs.declare("bsdf", InputFormatEntity, "");
            m_inputs.declare("bssrdf", InputFormatEntity, "");
            m_inputs.declare("edf", InputFormatEntity, "");
            m_inputs.declare("alpha_map", InputFormatFloat, "");
            m_inputs.declare("displacement_map", InputFormatSpectralReflectance, "");
            m_inputs.declare("phase_function", InputFormatEntity, "");
        }

        virtual void release() override
        {
            delete this;
        }

        virtual const char* get_model() const override
        {
            return Model;
        }

        virtual bool on_frame_begin(
            const Project&          project,
            const BaseGroup*        parent,
            OnFrameBeginRecorder&   recorder,
            IAbortSwitch*           abort_switch) override
        {
            if (!Material::on_frame_begin(project, parent, recorder, abort_switch))
                return false;

            const EntityDefMessageContext context("material", this);

            m_render_data.m_bsdf = get_uncached_bsdf();
            m_render_data.m_bssrdf = get_uncached_bssrdf();
            m_render_data.m_edf = get_uncached_edf();
            m_render_data.m_phase_function = get_uncached_phase_function();
            m_render_data.m_basis_modifier = create_basis_modifier(context);

            if (m_render_data.m_edf && m_render_data.m_alpha_map)
            {
                RENDERER_LOG_WARNING(
                    "%s: material is emitting light but may be partially or entirely transparent; "
                    "this may lead to unexpected or unphysical results.",
                    context.get());
            }

            return true;
        }
    };
}

//
// GenericMaterialFactory class implementation.
//

const char* GenericMaterialFactory::get_model() const
{
    return Model;
}

Dictionary GenericMaterialFactory::get_model_metadata() const
{
    return
        Dictionary()
            .insert("name", Model)
            .insert("label", "Generic Material");
}

DictionaryArray GenericMaterialFactory::get_input_metadata() const
{
    DictionaryArray metadata;

    add_surface_shader_metadata(metadata);

    metadata.push_back(
        Dictionary()
            .insert("name", "bsdf")
            .insert("label", "BSDF")
            .insert("type", "entity")
            .insert("entity_types", Dictionary().insert("bsdf", "BSDF"))
            .insert("use", "optional"));

    metadata.push_back(
        Dictionary()
            .insert("name", "bssrdf")
            .insert("label", "BSSRDF")
            .insert("type", "entity")
            .insert("entity_types", Dictionary().insert("bssrdf", "BSSRDF"))
            .insert("use", "optional"));

    metadata.push_back(
        Dictionary()
            .insert("name", "edf")
            .insert("label", "EDF")
            .insert("type", "entity")
            .insert("entity_types", Dictionary().insert("edf", "EDF"))
            .insert("use", "optional"));

    add_alpha_map_metadata(metadata);
    add_displacement_metadata(metadata);

    metadata.push_back(
        Dictionary()
        .insert("name", "phase_function")
        .insert("label", "Phase Function")
        .insert("type", "entity")
        .insert("entity_types",
            Dictionary().insert("phase_function", "Phase Function"))
        .insert("use", "optional"));

    return metadata;
}

auto_release_ptr<Material> GenericMaterialFactory::create(
    const char*         name,
    const ParamArray&   params) const
{
    return auto_release_ptr<Material>(new GenericMaterial(name, params));
}

auto_release_ptr<Material> GenericMaterialFactory::static_create(
    const char*         name,
    const ParamArray&   params)
{
    return auto_release_ptr<Material>(new GenericMaterial(name, params));
}

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

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

// appleseed.renderer headers.
#include "renderer/modeling/material/material.h"

// appleseed.foundation headers.
#include "foundation/utility/api/specializedapiarrays.h"
#include "foundation/utility/containers/dictionary.h"

using namespace foundation;

namespace renderer
{

namespace
{
    //
    // Generic material.
    //

    const char* Model = "generic_material";

    class GenericMaterial
      : public Material
    {
      public:
        GenericMaterial(
            const char*             name,
            const ParamArray&       params)
          : Material(name, params)
        {
            m_inputs.declare("bsdf", InputFormatEntity, "");
            m_inputs.declare("bssrdf", InputFormatEntity, "");
            m_inputs.declare("edf", InputFormatEntity, "");
            m_inputs.declare("alpha_map", InputFormatFloat, "");
            m_inputs.declare("displacement_map", InputFormatSpectralReflectance, "");
            m_inputs.declare("phase_function", InputFormatEntity, "");
        }

        virtual void release() override
        {
            delete this;
        }

        virtual const char* get_model() const override
        {
            return Model;
        }

        virtual bool on_frame_begin(
            const Project&          project,
            const BaseGroup*        parent,
            OnFrameBeginRecorder&   recorder,
            IAbortSwitch*           abort_switch) override
        {
            if (!Material::on_frame_begin(project, parent, recorder, abort_switch))
                return false;

            const EntityDefMessageContext context("material", this);

            m_render_data.m_bsdf = get_uncached_bsdf();
            m_render_data.m_bssrdf = get_uncached_bssrdf();
            m_render_data.m_edf = get_uncached_edf();
            m_render_data.m_phase_function = get_uncached_phase_function();
            m_render_data.m_basis_modifier = create_basis_modifier(context);

            if (m_render_data.m_edf && m_render_data.m_alpha_map)
            {
                RENDERER_LOG_WARNING(
                    "%s: material is emitting light but may be partially or entirely transparent; "
                    "this may lead to unexpected or unphysical results.",
                    context.get());
            }

            return true;
        }
    };
}

//
// GenericMaterialFactory class implementation.
//

const char* GenericMaterialFactory::get_model() const
{
    return Model;
}

Dictionary GenericMaterialFactory::get_model_metadata() const
{
    return
        Dictionary()
            .insert("name", Model)
            .insert("label", "Generic Material");
}

DictionaryArray GenericMaterialFactory::get_input_metadata() const
{
    DictionaryArray metadata;

    add_surface_shader_metadata(metadata);

    metadata.push_back(
        Dictionary()
            .insert("name", "bsdf")
            .insert("label", "BSDF")
            .insert("type", "entity")
            .insert("entity_types", Dictionary().insert("bsdf", "BSDF"))
            .insert("use", "optional"));

    metadata.push_back(
        Dictionary()
            .insert("name", "bssrdf")
            .insert("label", "BSSRDF")
            .insert("type", "entity")
            .insert("entity_types", Dictionary().insert("bssrdf", "BSSRDF"))
            .insert("use", "optional"));

    metadata.push_back(
        Dictionary()
            .insert("name", "edf")
            .insert("label", "EDF")
            .insert("type", "entity")
            .insert("entity_types", Dictionary().insert("edf", "EDF"))
            .insert("use", "optional"));

    metadata.push_back(
        Dictionary()
        .insert("name", "phase_function")
        .insert("label", "Phase Function")
        .insert("type", "entity")
        .insert("entity_types",
            Dictionary().insert("phase_function", "Phase Function"))
        .insert("use", "optional"));

    add_alpha_map_metadata(metadata);
    add_displacement_metadata(metadata);

    return metadata;
}

auto_release_ptr<Material> GenericMaterialFactory::create(
    const char*         name,
    const ParamArray&   params) const
{
    return auto_release_ptr<Material>(new GenericMaterial(name, params));
}

auto_release_ptr<Material> GenericMaterialFactory::static_create(
    const char*         name,
    const ParamArray&   params)
{
    return auto_release_ptr<Material>(new GenericMaterial(name, params));
}

}   // namespace renderer
<|endoftext|>