<commit_before>/*******************************************************************************
 * src/benchmark.cpp
 *
 * Copyright (C) 2017 Florian Kurpicz <florian.kurpicz@tu-dortmund.de>
 *
 * All rights reserved. Published under the BSD-2 license in the LICENSE file.
 ******************************************************************************/

#include <tclap/CmdLine.h>
#include <vector>

#include "benchmark/algorithm.hpp"
#include "benchmark/file_util.hpp"

#ifdef MALLOC_COUNT
#include "benchmark/malloc_count.h"
#endif // MALLOC_COUNT

auto filter_parallel(bool only_parallel, bool is_parallel) {
  return (!only_parallel || is_parallel);
}

auto filter_sequential(bool sequential, bool is_parallel) {
  return (!sequential || !is_parallel);
}

auto filter_wavelet_type(bool is_tree, bool no_trees, bool no_matrices) {
  return (is_tree ? !no_trees : !no_matrices);
}

int32_t main(int32_t argc, char const* argv[]) {
  TCLAP::CmdLine cmd("Benchmark for wavelet tree (and matrix) construction",
    ' ', "0.2");

  TCLAP::SwitchArg list_all_algorithms("l", "list",
    "Print the name and description of all registered algorithms", false);
  cmd.add(list_all_algorithms);
  TCLAP::MultiArg<std::string> file_path_arg("f", "file",
    "Path to the text file.", false, "string");
  cmd.add(file_path_arg);
  TCLAP::ValueArg<std::string> filter_arg("n", "name",
    "Runs all algorithms that contain the <name> in their name", false, "",
    "string");
  cmd.add(filter_arg);
  TCLAP::ValueArg<int32_t> word_width_arg("b", "byte",
    "Bytes per char in the input text.", false, 1, "uint8_t");
  cmd.add(word_width_arg);
  TCLAP::ValueArg<int32_t> nr_runs_arg("r", "runs",
    "Number of repetitions of the construction algorithm.",
    false, 5, "int32_t");
  cmd.add(nr_runs_arg);
  TCLAP::SwitchArg run_only_parallel_arg("p", "parallel",
    "Run only parallel construction algorithms.", false);
  cmd.add(run_only_parallel_arg);
  TCLAP::SwitchArg run_only_sequential_arg("s", "sequential",
    "Run only sequential construction algorithms.", false);
  cmd.add(run_only_sequential_arg);
  TCLAP::SwitchArg no_trees_arg("m", "no_trees",
    "Skip all wavelet trees construction algorithms.", false);
  cmd.add(no_trees_arg);
  TCLAP::SwitchArg no_matrices_arg("t", "no_matrices",
    "Skip all wavelet matrices construction algorithms.", false);
  cmd.add(no_matrices_arg);
  TCLAP::SwitchArg memory_arg("", "memory",
    "Compute peak memory during construction.", false);
  cmd.add(memory_arg);
  cmd.parse( argc, argv );

  auto& algo_list = algorithm_list::get_algorithm_list();
  if (list_all_algorithms.getValue()) {
    for (const auto& a : algo_list) {
      a->print_info();
    }
    return 0;
  }

  const std::vector<std::string> file_paths = file_path_arg.getValue();
  std::string filter = filter_arg.getValue();
  const int32_t word_width = word_width_arg.getValue();
  const int32_t nr_runs = nr_runs_arg.getValue();
  const bool run_only_parallel = run_only_parallel_arg.getValue();
  const bool run_only_sequential = run_only_sequential_arg.getValue();
  const bool no_trees = no_trees_arg.getValue();
  const bool no_matrices = no_matrices_arg.getValue();
  const bool memory = memory_arg.getValue();

  for (const auto& path : file_paths) {
    std::cout << std::endl << "Text: " << path << std::endl;
    void* txt_prt = nullptr;
    uint64_t text_size = 0;
    uint64_t levels = 0;
    std::vector<uint8_t> text_uint8;
    std::vector<uint16_t> text_uint16;
    std::vector<uint32_t> text_uint32;
    std::vector<uint64_t> text_uint64;
    if (word_width == 1) {
      text_uint8 = file_to_vector<1>(path);
      text_size = text_uint8.size();
      levels = reduce_alphabet(text_uint8);
      txt_prt = &text_uint8;
    } else if (word_width == 2) {
      text_uint16 = file_to_vector<2>(path);
      text_size = text_uint16.size();
      levels = reduce_alphabet(text_uint16);
      txt_prt = &text_uint16;
    } else if (word_width == 4) {
      text_uint32 = file_to_vector<4>(path);
      text_size = text_uint32.size();
      levels = reduce_alphabet(text_uint32);
      txt_prt = &text_uint32;
    } else if (word_width == 8) {
      text_uint64 = file_to_vector<8>(path);
      text_size = text_uint64.size();
      levels = reduce_alphabet(text_uint64);
      txt_prt = &text_uint64;
    } else {
      std::cerr << "You entered an invalid number of bytes per character "
                   "(parameter 'b')." << std::endl;
      return -1;
    }
#ifdef MALLOC_COUNT
    std::cout << "Memory peak text: " << malloc_count_peak() << ", MB: "
              << malloc_count_peak() / (1024 * 1024) << std::endl;
#endif // MALLOC_COUNT
    for (const auto& a : algo_list) {
      if (filter == "" || (a->name().find(filter) != std::string::npos)) {
        if (a->word_width() == word_width) {
          if (filter_parallel(run_only_parallel, a->is_parallel())) {
            if (filter_sequential(run_only_sequential, a->is_parallel())) {
              if (filter_wavelet_type(a->is_tree(), no_trees, no_matrices)) {
                a->print_info();
                if (memory) {
#ifdef MALLOC_COUNT
                  malloc_count_reset_peak();
                  a->memory_peak(txt_prt, text_size, levels);
                  std::cout << malloc_count_peak() << ", MB: "
                            << malloc_count_peak() / (1024 * 1024) << std::endl;
#else
                  std::cout << "Memory measurement is NOT enabled."
                            << std::endl;
#endif // MALLOC_COUNT
                } else {
                  std::cout << a->median_time(
                    txt_prt, text_size, levels, nr_runs) << std::endl;
                }
              }
            }
          }
        }
      }
    }
  }
  return 0;
}

/******************************************************************************/
<commit_msg>Fix file size measurement and enhance output<commit_after>/*******************************************************************************
 * src/benchmark.cpp
 *
 * Copyright (C) 2017 Florian Kurpicz <florian.kurpicz@tu-dortmund.de>
 *
 * All rights reserved. Published under the BSD-2 license in the LICENSE file.
 ******************************************************************************/

#include <tclap/CmdLine.h>
#include <vector>

#include "benchmark/algorithm.hpp"
#include "benchmark/file_util.hpp"

#ifdef MALLOC_COUNT
#include "benchmark/malloc_count.h"
#endif // MALLOC_COUNT

auto filter_parallel(bool only_parallel, bool is_parallel) {
  return (!only_parallel || is_parallel);
}

auto filter_sequential(bool sequential, bool is_parallel) {
  return (!sequential || !is_parallel);
}

auto filter_wavelet_type(bool is_tree, bool no_trees, bool no_matrices) {
  return (is_tree ? !no_trees : !no_matrices);
}

int32_t main(int32_t argc, char const* argv[]) {
  TCLAP::CmdLine cmd("Benchmark for wavelet tree (and matrix) construction",
    ' ', "0.2");

  TCLAP::SwitchArg list_all_algorithms("l", "list",
    "Print the name and description of all registered algorithms", false);
  cmd.add(list_all_algorithms);
  TCLAP::MultiArg<std::string> file_path_arg("f", "file",
    "Path to the text file.", false, "string");
  cmd.add(file_path_arg);
  TCLAP::ValueArg<std::string> filter_arg("n", "name",
    "Runs all algorithms that contain the <name> in their name", false, "",
    "string");
  cmd.add(filter_arg);
  TCLAP::ValueArg<int32_t> word_width_arg("b", "byte",
    "Bytes per char in the input text.", false, 1, "uint8_t");
  cmd.add(word_width_arg);
  TCLAP::ValueArg<int32_t> nr_runs_arg("r", "runs",
    "Number of repetitions of the construction algorithm.",
    false, 5, "int32_t");
  cmd.add(nr_runs_arg);
  TCLAP::SwitchArg run_only_parallel_arg("p", "parallel",
    "Run only parallel construction algorithms.", false);
  cmd.add(run_only_parallel_arg);
  TCLAP::SwitchArg run_only_sequential_arg("s", "sequential",
    "Run only sequential construction algorithms.", false);
  cmd.add(run_only_sequential_arg);
  TCLAP::SwitchArg no_trees_arg("m", "no_trees",
    "Skip all wavelet trees construction algorithms.", false);
  cmd.add(no_trees_arg);
  TCLAP::SwitchArg no_matrices_arg("t", "no_matrices",
    "Skip all wavelet matrices construction algorithms.", false);
  cmd.add(no_matrices_arg);
  TCLAP::SwitchArg memory_arg("", "memory",
    "Compute peak memory during construction.", false);
  cmd.add(memory_arg);
  cmd.parse( argc, argv );

  auto& algo_list = algorithm_list::get_algorithm_list();
  if (list_all_algorithms.getValue()) {
    for (const auto& a : algo_list) {
      a->print_info();
    }
    return 0;
  }

  const std::vector<std::string> file_paths = file_path_arg.getValue();
  std::string filter = filter_arg.getValue();
  const int32_t word_width = word_width_arg.getValue();
  const int32_t nr_runs = nr_runs_arg.getValue();
  const bool run_only_parallel = run_only_parallel_arg.getValue();
  const bool run_only_sequential = run_only_sequential_arg.getValue();
  const bool no_trees = no_trees_arg.getValue();
  const bool no_matrices = no_matrices_arg.getValue();
  const bool memory = memory_arg.getValue();

  for (const auto& path : file_paths) {
    std::cout << std::endl << "Text: " << path << std::endl;
    void* txt_prt = nullptr;
    uint64_t text_size = 0;
    uint64_t levels = 0;
    std::vector<uint8_t> text_uint8;
    std::vector<uint16_t> text_uint16;
    std::vector<uint32_t> text_uint32;
    std::vector<uint64_t> text_uint64;
#ifdef MALLOC_COUNT
    malloc_count_reset_peak();
#endif
    if (word_width == 1) {
      text_uint8 = file_to_vector<1>(path);
      text_size = text_uint8.size();
      levels = reduce_alphabet(text_uint8);
      txt_prt = &text_uint8;
    } else if (word_width == 2) {
      text_uint16 = file_to_vector<2>(path);
      text_size = text_uint16.size();
      levels = reduce_alphabet(text_uint16);
      txt_prt = &text_uint16;
    } else if (word_width == 4) {
      text_uint32 = file_to_vector<4>(path);
      text_size = text_uint32.size();
      levels = reduce_alphabet(text_uint32);
      txt_prt = &text_uint32;
    } else if (word_width == 8) {
      text_uint64 = file_to_vector<8>(path);
      text_size = text_uint64.size();
      levels = reduce_alphabet(text_uint64);
      txt_prt = &text_uint64;
    } else {
      std::cerr << "You entered an invalid number of bytes per character "
                   "(parameter 'b')." << std::endl;
      return -1;
    }
    std::cout << "Characters: " << text_size << std::endl;
#ifdef MALLOC_COUNT
    std::cout << "Memory peak text: " << malloc_count_peak() << ", MB: "
              << malloc_count_peak() / (1024 * 1024) << std::endl;
#endif // MALLOC_COUNT
    for (const auto& a : algo_list) {
      if (filter == "" || (a->name().find(filter) != std::string::npos)) {
        if (a->word_width() == word_width) {
          if (filter_parallel(run_only_parallel, a->is_parallel())) {
            if (filter_sequential(run_only_sequential, a->is_parallel())) {
              if (filter_wavelet_type(a->is_tree(), no_trees, no_matrices)) {
                a->print_info();
                if (memory) {
#ifdef MALLOC_COUNT
                  malloc_count_reset_peak();
                  a->memory_peak(txt_prt, text_size, levels);
                  std::cout << malloc_count_peak() << ", MB: "
                            << malloc_count_peak() / (1024 * 1024) << std::endl;
#else
                  std::cout << "Memory measurement is NOT enabled."
                            << std::endl;
#endif // MALLOC_COUNT
                } else {
                  std::cout << a->median_time(
                    txt_prt, text_size, levels, nr_runs) << std::endl;
                }
              }
            }
          }
        }
      }
    }
  }
  return 0;
}

/******************************************************************************/
<|endoftext|>


<commit_before>//
// PROJECT:         Aspia
// FILE:            codec/pixel_translator.h
// LICENSE:         GNU General Public License 3
// PROGRAMMERS:     Dmitry Chapyshev (dmitry@aspia.ru)
//

#include "codec/pixel_translator.h"

#include <vector>

namespace aspia {

namespace {

template<int source_bpp, int target_bpp>
class PixelTranslatorT : public PixelTranslator
{
public:
    PixelTranslatorT(const PixelFormat& source_format, const PixelFormat& target_format)
        : source_format_(source_format),
          target_format_(target_format)
    {
        red_table_.resize(source_format_.redMax() + 1);
        green_table_.resize(source_format_.greenMax() + 1);
        blue_table_.resize(source_format_.blueMax() + 1);

        for (quint32 i = 0; i <= source_format_.redMax(); ++i)
        {
            red_table_[i] = ((i * target_format_.redMax() + source_format_.redMax() / 2) /
                             source_format_.redMax()) << target_format_.redShift();
        }

        for (quint32 i = 0; i <= source_format_.greenMax(); ++i)
        {
            green_table_[i] = ((i * target_format_.greenMax() + source_format_.greenMax() / 2) /
                               source_format_.greenMax()) << target_format_.greenShift();
        }

        for (quint32 i = 0; i <= source_format_.blueMax(); ++i)
        {
            blue_table_[i] = ((i * target_format_.blueMax() + source_format_.blueMax() / 2) /
                              source_format_.blueMax()) << target_format_.blueShift();
        }
    }

    ~PixelTranslatorT() = default;

    void translate(const quint8* src, int src_stride,
                   quint8* dst, int dst_stride,
                   int width, int height) override
    {
        src_stride -= width * source_bpp;
        dst_stride -= width * target_bpp;

        for (int y = 0; y < height; ++y)
        {
            for (int x = 0; x < width; ++x)
            {
                quint32 red;
                quint32 green;
                quint32 blue;

                if constexpr (source_bpp == 4)
                {
                    red = red_table_[
                        *(quint32*) src >> source_format_.redShift() & source_format_.redMax()];
                    green = green_table_[
                        *(quint32*) src >> source_format_.greenShift() & source_format_.greenMax()];
                    blue = blue_table_[
                        *(quint32*) src >> source_format_.blueShift() & source_format_.blueMax()];
                }
                else if constexpr (source_bpp == 2)
                {
                    red = red_table_[
                        *(quint16*) src >> source_format_.redShift() & source_format_.redMax()];
                    green = green_table_[
                        *(quint16*) src >> source_format_.greenShift() & source_format_.greenMax()];
                    blue = blue_table_[
                        *(quint16*) src >> source_format_.blueShift() & source_format_.blueMax()];
                }
                else if constexpr (source_bpp == 1)
                {
                    red = red_table_[
                        *(quint8*) src >> source_format_.redShift() & source_format_.redMax()];
                    green = green_table_[
                        *(quint8*) src >> source_format_.greenShift() & source_format_.greenMax()];
                    blue = blue_table_[
                        *(quint8*) src >> source_format_.blueShift() & source_format_.blueMax()];
                }
                else
                {
                    red = green = blue = 0;
                    qFatal("Unexpected pixel format");
                }

                if constexpr (target_bpp == 4)
                    *(quint32*) dst = static_cast<quint32>(red | green | blue);
                else if constexpr (target_bpp == 2)
                    *(quint16*) dst = static_cast<quint16>(red | green | blue);
                else if constexpr (target_bpp == 1)
                    *(quint8*) dst = static_cast<quint8>(red | green | blue);

                src += source_bpp;
                dst += target_bpp;
            }

            src += src_stride;
            dst += dst_stride;
        }
    }

private:
    std::vector<quint32> red_table_;
    std::vector<quint32> green_table_;
    std::vector<quint32> blue_table_;

    PixelFormat source_format_;
    PixelFormat target_format_;

    Q_DISABLE_COPY(PixelTranslatorT)
};

} // namespace

// static
std::unique_ptr<PixelTranslator> PixelTranslator::create(const PixelFormat& source_format,
                                                         const PixelFormat& target_format)
{
    switch (target_format.bytesPerPixel())
    {
        case 4:
        {
            switch (source_format.bytesPerPixel())
            {
                case 4:
                    return std::make_unique<PixelTranslatorT<4, 4>>(source_format, target_format);

                case 2:
                    return std::make_unique<PixelTranslatorT<2, 4>>(source_format, target_format);

                case 1:
                    return std::make_unique<PixelTranslatorT<1, 4>>(source_format, target_format);
            }
        }
        break;

        case 2:
        {
            switch (source_format.bytesPerPixel())
            {
                case 4:
                    return std::make_unique<PixelTranslatorT<4, 2>>(source_format, target_format);

                case 2:
                    return std::make_unique<PixelTranslatorT<2, 2>>(source_format, target_format);

                case 1:
                    return std::make_unique<PixelTranslatorT<1, 2>>(source_format, target_format);
            }
        }
        break;

        case 1:
        {
            switch (source_format.bytesPerPixel())
            {
                case 4:
                    return std::make_unique<PixelTranslatorT<4, 1>>(source_format, target_format);

                case 2:
                    return std::make_unique<PixelTranslatorT<2, 1>>(source_format, target_format);

                case 1:
                    return std::make_unique<PixelTranslatorT<1, 1>>(source_format, target_format);
            }
        }
        break;
    }

    return nullptr;
}

} // namespace aspia
<commit_msg>- Using std::unique_ptr instead std::vector.<commit_after>//
// PROJECT:         Aspia
// FILE:            codec/pixel_translator.h
// LICENSE:         GNU General Public License 3
// PROGRAMMERS:     Dmitry Chapyshev (dmitry@aspia.ru)
//

#include "codec/pixel_translator.h"

namespace aspia {

namespace {

template<int source_bpp, int target_bpp>
class PixelTranslatorT : public PixelTranslator
{
public:
    PixelTranslatorT(const PixelFormat& source_format, const PixelFormat& target_format)
        : source_format_(source_format),
          target_format_(target_format)
    {
        red_table_ = std::make_unique<quint32[]>(source_format_.redMax() + 1);
        green_table_ = std::make_unique<quint32[]>(source_format_.greenMax() + 1);
        blue_table_ = std::make_unique<quint32[]>(source_format_.blueMax() + 1);

        for (quint32 i = 0; i <= source_format_.redMax(); ++i)
        {
            red_table_[i] = ((i * target_format_.redMax() + source_format_.redMax() / 2) /
                             source_format_.redMax()) << target_format_.redShift();
        }

        for (quint32 i = 0; i <= source_format_.greenMax(); ++i)
        {
            green_table_[i] = ((i * target_format_.greenMax() + source_format_.greenMax() / 2) /
                               source_format_.greenMax()) << target_format_.greenShift();
        }

        for (quint32 i = 0; i <= source_format_.blueMax(); ++i)
        {
            blue_table_[i] = ((i * target_format_.blueMax() + source_format_.blueMax() / 2) /
                              source_format_.blueMax()) << target_format_.blueShift();
        }
    }

    ~PixelTranslatorT() = default;

    void translate(const quint8* src, int src_stride,
                   quint8* dst, int dst_stride,
                   int width, int height) override
    {
        src_stride -= width * source_bpp;
        dst_stride -= width * target_bpp;

        for (int y = 0; y < height; ++y)
        {
            for (int x = 0; x < width; ++x)
            {
                quint32 red;
                quint32 green;
                quint32 blue;

                if constexpr (source_bpp == 4)
                {
                    red = red_table_[
                        *(quint32*) src >> source_format_.redShift() & source_format_.redMax()];
                    green = green_table_[
                        *(quint32*) src >> source_format_.greenShift() & source_format_.greenMax()];
                    blue = blue_table_[
                        *(quint32*) src >> source_format_.blueShift() & source_format_.blueMax()];
                }
                else if constexpr (source_bpp == 2)
                {
                    red = red_table_[
                        *(quint16*) src >> source_format_.redShift() & source_format_.redMax()];
                    green = green_table_[
                        *(quint16*) src >> source_format_.greenShift() & source_format_.greenMax()];
                    blue = blue_table_[
                        *(quint16*) src >> source_format_.blueShift() & source_format_.blueMax()];
                }
                else if constexpr (source_bpp == 1)
                {
                    red = red_table_[
                        *(quint8*) src >> source_format_.redShift() & source_format_.redMax()];
                    green = green_table_[
                        *(quint8*) src >> source_format_.greenShift() & source_format_.greenMax()];
                    blue = blue_table_[
                        *(quint8*) src >> source_format_.blueShift() & source_format_.blueMax()];
                }

                if constexpr (target_bpp == 4)
                    *(quint32*) dst = static_cast<quint32>(red | green | blue);
                else if constexpr (target_bpp == 2)
                    *(quint16*) dst = static_cast<quint16>(red | green | blue);
                else if constexpr (target_bpp == 1)
                    *(quint8*) dst = static_cast<quint8>(red | green | blue);

                src += source_bpp;
                dst += target_bpp;
            }

            src += src_stride;
            dst += dst_stride;
        }
    }

private:
    std::unique_ptr<quint32[]> red_table_;
    std::unique_ptr<quint32[]> green_table_;
    std::unique_ptr<quint32[]> blue_table_;

    PixelFormat source_format_;
    PixelFormat target_format_;

    Q_DISABLE_COPY(PixelTranslatorT)
};

} // namespace

// static
std::unique_ptr<PixelTranslator> PixelTranslator::create(const PixelFormat& source_format,
                                                         const PixelFormat& target_format)
{
    switch (target_format.bytesPerPixel())
    {
        case 4:
        {
            switch (source_format.bytesPerPixel())
            {
                case 4:
                    return std::make_unique<PixelTranslatorT<4, 4>>(source_format, target_format);

                case 2:
                    return std::make_unique<PixelTranslatorT<2, 4>>(source_format, target_format);

                case 1:
                    return std::make_unique<PixelTranslatorT<1, 4>>(source_format, target_format);
            }
        }
        break;

        case 2:
        {
            switch (source_format.bytesPerPixel())
            {
                case 4:
                    return std::make_unique<PixelTranslatorT<4, 2>>(source_format, target_format);

                case 2:
                    return std::make_unique<PixelTranslatorT<2, 2>>(source_format, target_format);

                case 1:
                    return std::make_unique<PixelTranslatorT<1, 2>>(source_format, target_format);
            }
        }
        break;

        case 1:
        {
            switch (source_format.bytesPerPixel())
            {
                case 4:
                    return std::make_unique<PixelTranslatorT<4, 1>>(source_format, target_format);

                case 2:
                    return std::make_unique<PixelTranslatorT<2, 1>>(source_format, target_format);

                case 1:
                    return std::make_unique<PixelTranslatorT<1, 1>>(source_format, target_format);
            }
        }
        break;
    }

    return nullptr;
}

} // namespace aspia
<|endoftext|>


<commit_before>//***************************************************************************************************************************************************
//* BSD 3-Clause License
//*
//* Copyright (c) 2016, Rene Thrane
//* All rights reserved.
//*
//* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
//*
//* 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
//* 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the
//*    documentation and/or other materials provided with the distribution.
//* 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this
//*    software without specific prior written permission.
//*
//* THIS SOFTWARE IS PROVIDED BY THE 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 HOLDER OR
//* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
//* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
//* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
//* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//***************************************************************************************************************************************************

#include <RAIIGen/Generator/VulkanGenerator.hpp>
#include <RAIIGen/Generator/FunctionNamePair.hpp>
#include <RAIIGen/Generator/MatchedFunctionPair.hpp>
#include <RAIIGen/Generator/RAIIClassCustomization.hpp>
#include <RAIIGen/Generator/RAIIClassMethodOverrides.hpp>
#include <RAIIGen/CaseUtil.hpp>
#include <RAIIGen/Capture.hpp>
#include <FslBase/Exceptions.hpp>
#include <FslBase/IO/File.hpp>
#include <FslBase/String/StringUtil.hpp>
#include <algorithm>
#include <array>
#include <iostream>
#include <string>
#include <unordered_map>
#include <unordered_set>

using namespace Fsl;

namespace MB
{
  namespace
  {
    // OpenCL
    // const auto VULKAN_CREATE_FUNCTION = "clCreate";
    // const auto VULKAN_DESTROY_FUNCTION = "clDestroy";
    // const auto VULKAN_ALLOCATE_FUNCTION = "clAllocate";
    // const auto VULKAN_FREE_FUNCTION = "clFree";

    const auto CREATE_FUNCTION = "vkCreate";
    const auto DESTROY_FUNCTION = "vkDestroy";
    const auto ALLOCATE_FUNCTION = "vkAllocate";
    const auto FREE_FUNCTION = "vkFree";

    const auto TYPE_NAME_PREFIX = "Vk";
    const auto FUNCTION_NAME_PREFIX = "vk";

    const auto DEFAULT_VALUE = "VK_NULL_HANDLE";

    const auto ERRORCODE_TYPE_NAME = "VkResult";

    const std::vector<FunctionNamePair> g_functionPairs{FunctionNamePair(CREATE_FUNCTION, DESTROY_FUNCTION),
                                                        FunctionNamePair(ALLOCATE_FUNCTION, FREE_FUNCTION)};

    // Manual matches for methods that don't follow 'standard' patterns
    const std::vector<FunctionNamePair> g_manualFunctionMatches{
      // Pipelines are destroyed with vkDestroyPipeline
      FunctionNamePair("vkCreateGraphicsPipelines", "vkDestroyPipeline"),
      FunctionNamePair("vkCreateComputePipelines", "vkDestroyPipeline"),
      FunctionNamePair("vkCreateDisplayPlaneSurfaceKHR", "vkDestroySurfaceKHR"),
      FunctionNamePair("vkCreateRenderPass2", "vkDestroyRenderPass"),
      FunctionNamePair("vkCreateHeadlessSurfaceEXT", " vkDestroySurfaceKHR"),
    };

    const std::vector<RAIIClassCustomization> g_arrayRAIIClassCustomization{
      RAIIClassCustomization("vkAllocateCommandBuffers", "CommandBuffer", "CommandBuffers", "commandBuffers", "commandBufferCount", ""),
      RAIIClassCustomization("vkAllocateDescriptorSets", "DescriptorSet", "DescriptorSets", "descriptorSets", "descriptorSetCount", ""),
      RAIIClassCustomization("vkCreateComputePipelines", "ComputePipeline", "ComputePipelines", "computePipelines", "", "createInfoCount",
                             SourceTemplateType::ArrayAllocationButSingleInstanceDestroy, {"pCreateInfos"}, true, false),
      RAIIClassCustomization("vkCreateGraphicsPipelines", "GraphicsPipeline", "GraphicsPipelines", "graphicsPipelines", "", "createInfoCount",
                             SourceTemplateType::ArrayAllocationButSingleInstanceDestroy, {"pCreateInfos"}, true, false),
    };

    const std::vector<ClassFunctionAbsorb> g_classFunctionAbsorbtion{};

    const std::unordered_map<std::string, RAIIClassMethodOverrides> g_classMethodOverride = {
      {"SwapchainKHR", RAIIClassMethodOverrides("TemplateSnippet_ResetMemberHeader_CustomSwapchain.txt")},
    };

    const std::vector<std::string> g_forceNullParameter{"VkAllocationCallbacks"};

    const std::vector<FunctionGuard> g_functionGuards{
      // FunctionGuard("vkGetSwapchainStatusKHR", "VK_HEADER_VERSION >= 49")
    };

    const std::vector<BlackListEntry> g_functionNameBlacklist{
      BlackListEntry("GetFenceStatus", BlackListMatch::Exact),        BlackListEntry("EXT", BlackListMatch::PostfixNotEntityName),
      BlackListEntry("GOOGLE", BlackListMatch::PostfixNotEntityName), BlackListEntry("KHR", BlackListMatch::PostfixNotEntityName),
      BlackListEntry("KHX", BlackListMatch::PostfixNotEntityName),    BlackListEntry("AMD", BlackListMatch::PostfixNotEntityName),
      BlackListEntry("NVX", BlackListMatch::PostfixNotEntityName),    BlackListEntry("NV", BlackListMatch::PostfixNotEntityName),
      BlackListEntry("INTEL", BlackListMatch::PostfixNotEntityName),
    };

    const std::vector<BlackListEntry> g_enumNameBlacklist{
      // BlackListEntry("AMD", BlackListMatch::Always),
      // BlackListEntry("EXT", BlackListMatch::Always),
      // BlackListEntry("GOOGLE", BlackListMatch::Always),
      // BlackListEntry("KHR", BlackListMatch::Always),
      // BlackListEntry("KHX", BlackListMatch::Always),
      // BlackListEntry("NV", BlackListMatch::Always),
      // BlackListEntry("NVX", BlackListMatch::Always),
    };

    const std::vector<BlackListEntry> g_enumMemberBlacklist{
      BlackListEntry("_BEGIN_RANGE", BlackListMatch::Postfix),
      BlackListEntry("_END_RANGE", BlackListMatch::Postfix),
      BlackListEntry("_RANGE_SIZE", BlackListMatch::Postfix),
      BlackListEntry("_MAX_ENUM", BlackListMatch::Postfix),

      BlackListEntry("_BEGIN_RANGE_", BlackListMatch::Contains),
      BlackListEntry("_END_RANGE_", BlackListMatch::Contains),
      BlackListEntry("_RANGE_SIZE_", BlackListMatch::Contains),
      BlackListEntry("_MAX_ENUM_", BlackListMatch::Contains),

      BlackListEntry("_AMD", "AMD", BlackListMatch::PostfixNotEntityNameEx),
      BlackListEntry("_EXT", "EXT", BlackListMatch::PostfixNotEntityNameEx),
      BlackListEntry("_GOOGLE", "GOOGLE", BlackListMatch::PostfixNotEntityNameEx),
      BlackListEntry("_INTEL", "INTEL", BlackListMatch::PostfixNotEntityNameEx),
      BlackListEntry("_KHR", "KHR", BlackListMatch::PostfixNotEntityNameEx),
      BlackListEntry("_KHX", "KHX", BlackListMatch::PostfixNotEntityNameEx),
      BlackListEntry("_NV", "NV", BlackListMatch::PostfixNotEntityNameEx),
      BlackListEntry("_NVX", "NVX", BlackListMatch::PostfixNotEntityNameEx),
    };

    //! Not necessary for the Vulkan header as it was properly constructed!
    const std::vector<FunctionParameterNameOverride> g_functionParameterNameOverride{};

    const std::vector<FunctionParameterTypeOverride> g_functionParameterTypeOverride{};

    const std::unordered_map<std::string, std::string> g_typeDefaultValues = {
      {"VkBuffer", DEFAULT_VALUE},
      {"VkBufferView", DEFAULT_VALUE},
      {"VkCommandBuffer", DEFAULT_VALUE},
      {"VkCommandPool", DEFAULT_VALUE},
      {"VkDebugReportCallbackEXT", DEFAULT_VALUE},
      {"VkDescriptorPool", DEFAULT_VALUE},
      {"VkDescriptorSet", DEFAULT_VALUE},
      {"VkDescriptorSetLayout", DEFAULT_VALUE},
      {"VkDevice", DEFAULT_VALUE},
      {"VkDeviceMemory", DEFAULT_VALUE},
      {"VkEvent", DEFAULT_VALUE},
      {"VkFence", DEFAULT_VALUE},
      {"VkFramebuffer", DEFAULT_VALUE},
      {"VkImage", DEFAULT_VALUE},
      {"VkImageView", DEFAULT_VALUE},
      {"VkInstance", DEFAULT_VALUE},
      {"VkPipeline", DEFAULT_VALUE},
      {"VkPipelineCache", DEFAULT_VALUE},
      {"VkPipelineLayout", DEFAULT_VALUE},
      {"VkQueryPool", DEFAULT_VALUE},
      {"VkRenderPass", DEFAULT_VALUE},
      {"VkSampler", DEFAULT_VALUE},
      {"VkSemaphore", DEFAULT_VALUE},
      {"VkShaderModule", DEFAULT_VALUE},
      {"VkSurfaceKHR", DEFAULT_VALUE},
      {"VkSwapchainKHR", DEFAULT_VALUE},
      {"VkSamplerYcbcrConversionKHR", DEFAULT_VALUE},
      {"VkDescriptorUpdateTemplateKHR", DEFAULT_VALUE},
      {"VkIndirectCommandsLayoutNVX", DEFAULT_VALUE},
      {"VkObjectTableNVX", DEFAULT_VALUE},
      {"VkValidationCacheEXT", DEFAULT_VALUE},
      {"VkAccelerationStructureNV", DEFAULT_VALUE},
      {"VkDebugUtilsMessengerEXT", DEFAULT_VALUE},
      {"VkDescriptorUpdateTemplate", DEFAULT_VALUE},
      {"VkSamplerYcbcrConversion", DEFAULT_VALUE},
      {"VkIndirectCommandsLayoutNV", DEFAULT_VALUE},
      {"VkPrivateDataSlotEXT", DEFAULT_VALUE},
      {"VkAccelerationStructureKHR", DEFAULT_VALUE},
      {"VkDeferredOperationKHR", DEFAULT_VALUE},
      {"VkCuFunctionNVX", DEFAULT_VALUE},
      {"VkCuModuleNVX", DEFAULT_VALUE},
      {"VkPrivateDataSlot", DEFAULT_VALUE},
    };

    // Technically it would be better to do a real aliasing resolve, but its more complex to implement for now (but it is the real solution)
    const std::vector<TypeNameAliasEntry> g_typeNameAliases = {{"VkAccelerationStructureKHR", "VkAccelerationStructureNV"}};
  }

  VulkanGenerator::VulkanGenerator(const Capture& capture, const BasicConfig& basicConfig, const Fsl::IO::Path& templateRoot,
                                   const Fsl::IO::Path& dstPath)
    : SimpleGenerator(capture,
                      SimpleGeneratorConfig(basicConfig, g_functionPairs, g_manualFunctionMatches, g_arrayRAIIClassCustomization,
                                            g_classFunctionAbsorbtion, g_classMethodOverride, g_typeDefaultValues, g_forceNullParameter,
                                            g_functionGuards, g_functionNameBlacklist, g_enumNameBlacklist, g_enumMemberBlacklist,
                                            g_typeNameAliases, TYPE_NAME_PREFIX,
                                            FUNCTION_NAME_PREFIX, ERRORCODE_TYPE_NAME, true, true, VersionGuardConfig("VK_HEADER_VERSION >= {2}"),
                                            true),
                      templateRoot, dstPath)
  {
  }

  CaptureConfig VulkanGenerator::GetCaptureConfig()
  {
    std::deque<std::string> filters;
    // filters.push_back(CREATE_FUNCTION);
    // filters.push_back(DESTROY_FUNCTION);
    // filters.push_back(ALLOCATE_FUNCTION);
    // filters.push_back(FREE_FUNCTION);
    return CaptureConfig(TYPE_NAME_PREFIX, filters, g_functionParameterNameOverride, g_functionParameterTypeOverride, false);
  }
}
<commit_msg>Rapid vulkan 1.3.224.0<commit_after>//***************************************************************************************************************************************************
//* BSD 3-Clause License
//*
//* Copyright (c) 2016, Rene Thrane
//* All rights reserved.
//*
//* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
//*
//* 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
//* 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the
//*    documentation and/or other materials provided with the distribution.
//* 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this
//*    software without specific prior written permission.
//*
//* THIS SOFTWARE IS PROVIDED BY THE 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 HOLDER OR
//* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
//* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
//* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
//* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//***************************************************************************************************************************************************

#include <RAIIGen/Generator/VulkanGenerator.hpp>
#include <RAIIGen/Generator/FunctionNamePair.hpp>
#include <RAIIGen/Generator/MatchedFunctionPair.hpp>
#include <RAIIGen/Generator/RAIIClassCustomization.hpp>
#include <RAIIGen/Generator/RAIIClassMethodOverrides.hpp>
#include <RAIIGen/CaseUtil.hpp>
#include <RAIIGen/Capture.hpp>
#include <FslBase/Exceptions.hpp>
#include <FslBase/IO/File.hpp>
#include <FslBase/String/StringUtil.hpp>
#include <algorithm>
#include <array>
#include <iostream>
#include <string>
#include <unordered_map>
#include <unordered_set>

using namespace Fsl;

namespace MB
{
  namespace
  {
    // OpenCL
    // const auto VULKAN_CREATE_FUNCTION = "clCreate";
    // const auto VULKAN_DESTROY_FUNCTION = "clDestroy";
    // const auto VULKAN_ALLOCATE_FUNCTION = "clAllocate";
    // const auto VULKAN_FREE_FUNCTION = "clFree";

    const auto CREATE_FUNCTION = "vkCreate";
    const auto DESTROY_FUNCTION = "vkDestroy";
    const auto ALLOCATE_FUNCTION = "vkAllocate";
    const auto FREE_FUNCTION = "vkFree";

    const auto TYPE_NAME_PREFIX = "Vk";
    const auto FUNCTION_NAME_PREFIX = "vk";

    const auto DEFAULT_VALUE = "VK_NULL_HANDLE";

    const auto ERRORCODE_TYPE_NAME = "VkResult";

    const std::vector<FunctionNamePair> g_functionPairs{FunctionNamePair(CREATE_FUNCTION, DESTROY_FUNCTION),
                                                        FunctionNamePair(ALLOCATE_FUNCTION, FREE_FUNCTION)};

    // Manual matches for methods that don't follow 'standard' patterns
    const std::vector<FunctionNamePair> g_manualFunctionMatches{
      // Pipelines are destroyed with vkDestroyPipeline
      FunctionNamePair("vkCreateGraphicsPipelines", "vkDestroyPipeline"),
      FunctionNamePair("vkCreateComputePipelines", "vkDestroyPipeline"),
      FunctionNamePair("vkCreateDisplayPlaneSurfaceKHR", "vkDestroySurfaceKHR"),
      FunctionNamePair("vkCreateRenderPass2", "vkDestroyRenderPass"),
      FunctionNamePair("vkCreateHeadlessSurfaceEXT", " vkDestroySurfaceKHR"),
    };

    const std::vector<RAIIClassCustomization> g_arrayRAIIClassCustomization{
      RAIIClassCustomization("vkAllocateCommandBuffers", "CommandBuffer", "CommandBuffers", "commandBuffers", "commandBufferCount", ""),
      RAIIClassCustomization("vkAllocateDescriptorSets", "DescriptorSet", "DescriptorSets", "descriptorSets", "descriptorSetCount", ""),
      RAIIClassCustomization("vkCreateComputePipelines", "ComputePipeline", "ComputePipelines", "computePipelines", "", "createInfoCount",
                             SourceTemplateType::ArrayAllocationButSingleInstanceDestroy, {"pCreateInfos"}, true, false),
      RAIIClassCustomization("vkCreateGraphicsPipelines", "GraphicsPipeline", "GraphicsPipelines", "graphicsPipelines", "", "createInfoCount",
                             SourceTemplateType::ArrayAllocationButSingleInstanceDestroy, {"pCreateInfos"}, true, false),
    };

    const std::vector<ClassFunctionAbsorb> g_classFunctionAbsorbtion{};

    const std::unordered_map<std::string, RAIIClassMethodOverrides> g_classMethodOverride = {
      {"SwapchainKHR", RAIIClassMethodOverrides("TemplateSnippet_ResetMemberHeader_CustomSwapchain.txt")},
    };

    const std::vector<std::string> g_forceNullParameter{"VkAllocationCallbacks"};

    const std::vector<FunctionGuard> g_functionGuards{
      // FunctionGuard("vkGetSwapchainStatusKHR", "VK_HEADER_VERSION >= 49")
    };

    const std::vector<BlackListEntry> g_functionNameBlacklist{
      BlackListEntry("GetFenceStatus", BlackListMatch::Exact),        BlackListEntry("EXT", BlackListMatch::PostfixNotEntityName),
      BlackListEntry("GOOGLE", BlackListMatch::PostfixNotEntityName), BlackListEntry("KHR", BlackListMatch::PostfixNotEntityName),
      BlackListEntry("KHX", BlackListMatch::PostfixNotEntityName),    BlackListEntry("AMD", BlackListMatch::PostfixNotEntityName),
      BlackListEntry("NVX", BlackListMatch::PostfixNotEntityName),    BlackListEntry("NV", BlackListMatch::PostfixNotEntityName),
      BlackListEntry("INTEL", BlackListMatch::PostfixNotEntityName),  BlackListEntry("QCOM", BlackListMatch::PostfixNotEntityName),
      BlackListEntry("VALVE", BlackListMatch::PostfixNotEntityName)};

    const std::vector<BlackListEntry> g_enumNameBlacklist{
      // BlackListEntry("AMD", BlackListMatch::Always),
      // BlackListEntry("EXT", BlackListMatch::Always),
      // BlackListEntry("GOOGLE", BlackListMatch::Always),
      // BlackListEntry("KHR", BlackListMatch::Always),
      // BlackListEntry("KHX", BlackListMatch::Always),
      // BlackListEntry("NV", BlackListMatch::Always),
      // BlackListEntry("NVX", BlackListMatch::Always),
    };

    const std::vector<BlackListEntry> g_enumMemberBlacklist{
      BlackListEntry("_BEGIN_RANGE", BlackListMatch::Postfix),
      BlackListEntry("_END_RANGE", BlackListMatch::Postfix),
      BlackListEntry("_RANGE_SIZE", BlackListMatch::Postfix),
      BlackListEntry("_MAX_ENUM", BlackListMatch::Postfix),

      BlackListEntry("_BEGIN_RANGE_", BlackListMatch::Contains),
      BlackListEntry("_END_RANGE_", BlackListMatch::Contains),
      BlackListEntry("_RANGE_SIZE_", BlackListMatch::Contains),
      BlackListEntry("_MAX_ENUM_", BlackListMatch::Contains),

      BlackListEntry("_AMD", "AMD", BlackListMatch::PostfixNotEntityNameEx),
      BlackListEntry("_EXT", "EXT", BlackListMatch::PostfixNotEntityNameEx),
      BlackListEntry("_GOOGLE", "GOOGLE", BlackListMatch::PostfixNotEntityNameEx),
      BlackListEntry("_INTEL", "INTEL", BlackListMatch::PostfixNotEntityNameEx),
      BlackListEntry("_KHR", "KHR", BlackListMatch::PostfixNotEntityNameEx),
      BlackListEntry("_KHX", "KHX", BlackListMatch::PostfixNotEntityNameEx),
      BlackListEntry("_NV", "NV", BlackListMatch::PostfixNotEntityNameEx),
      BlackListEntry("_NVX", "NVX", BlackListMatch::PostfixNotEntityNameEx),
    };

    //! Not necessary for the Vulkan header as it was properly constructed!
    const std::vector<FunctionParameterNameOverride> g_functionParameterNameOverride{};

    const std::vector<FunctionParameterTypeOverride> g_functionParameterTypeOverride{};

    const std::unordered_map<std::string, std::string> g_typeDefaultValues = {
      {"VkBuffer", DEFAULT_VALUE},
      {"VkBufferView", DEFAULT_VALUE},
      {"VkCommandBuffer", DEFAULT_VALUE},
      {"VkCommandPool", DEFAULT_VALUE},
      {"VkDebugReportCallbackEXT", DEFAULT_VALUE},
      {"VkDescriptorPool", DEFAULT_VALUE},
      {"VkDescriptorSet", DEFAULT_VALUE},
      {"VkDescriptorSetLayout", DEFAULT_VALUE},
      {"VkDevice", DEFAULT_VALUE},
      {"VkDeviceMemory", DEFAULT_VALUE},
      {"VkEvent", DEFAULT_VALUE},
      {"VkFence", DEFAULT_VALUE},
      {"VkFramebuffer", DEFAULT_VALUE},
      {"VkImage", DEFAULT_VALUE},
      {"VkImageView", DEFAULT_VALUE},
      {"VkInstance", DEFAULT_VALUE},
      {"VkPipeline", DEFAULT_VALUE},
      {"VkPipelineCache", DEFAULT_VALUE},
      {"VkPipelineLayout", DEFAULT_VALUE},
      {"VkQueryPool", DEFAULT_VALUE},
      {"VkRenderPass", DEFAULT_VALUE},
      {"VkSampler", DEFAULT_VALUE},
      {"VkSemaphore", DEFAULT_VALUE},
      {"VkShaderModule", DEFAULT_VALUE},
      {"VkSurfaceKHR", DEFAULT_VALUE},
      {"VkSwapchainKHR", DEFAULT_VALUE},
      {"VkSamplerYcbcrConversionKHR", DEFAULT_VALUE},
      {"VkDescriptorUpdateTemplateKHR", DEFAULT_VALUE},
      {"VkIndirectCommandsLayoutNVX", DEFAULT_VALUE},
      {"VkObjectTableNVX", DEFAULT_VALUE},
      {"VkValidationCacheEXT", DEFAULT_VALUE},
      {"VkAccelerationStructureNV", DEFAULT_VALUE},
      {"VkDebugUtilsMessengerEXT", DEFAULT_VALUE},
      {"VkDescriptorUpdateTemplate", DEFAULT_VALUE},
      {"VkSamplerYcbcrConversion", DEFAULT_VALUE},
      {"VkIndirectCommandsLayoutNV", DEFAULT_VALUE},
      {"VkPrivateDataSlotEXT", DEFAULT_VALUE},
      {"VkAccelerationStructureKHR", DEFAULT_VALUE},
      {"VkDeferredOperationKHR", DEFAULT_VALUE},
      {"VkCuFunctionNVX", DEFAULT_VALUE},
      {"VkCuModuleNVX", DEFAULT_VALUE},
      {"VkPrivateDataSlot", DEFAULT_VALUE},
    };

    // Technically it would be better to do a real aliasing resolve, but its more complex to implement for now (but it is the real solution)
    const std::vector<TypeNameAliasEntry> g_typeNameAliases = {{"VkAccelerationStructureKHR", "VkAccelerationStructureNV"}};
  }

  VulkanGenerator::VulkanGenerator(const Capture& capture, const BasicConfig& basicConfig, const Fsl::IO::Path& templateRoot,
                                   const Fsl::IO::Path& dstPath)
    : SimpleGenerator(capture,
                      SimpleGeneratorConfig(basicConfig, g_functionPairs, g_manualFunctionMatches, g_arrayRAIIClassCustomization,
                                            g_classFunctionAbsorbtion, g_classMethodOverride, g_typeDefaultValues, g_forceNullParameter,
                                            g_functionGuards, g_functionNameBlacklist, g_enumNameBlacklist, g_enumMemberBlacklist,
                                            g_typeNameAliases, TYPE_NAME_PREFIX,
                                            FUNCTION_NAME_PREFIX, ERRORCODE_TYPE_NAME, true, true, VersionGuardConfig("VK_HEADER_VERSION >= {2}"),
                                            true),
                      templateRoot, dstPath)
  {
  }

  CaptureConfig VulkanGenerator::GetCaptureConfig()
  {
    std::deque<std::string> filters;
    // filters.push_back(CREATE_FUNCTION);
    // filters.push_back(DESTROY_FUNCTION);
    // filters.push_back(ALLOCATE_FUNCTION);
    // filters.push_back(FREE_FUNCTION);
    return CaptureConfig(TYPE_NAME_PREFIX, filters, g_functionParameterNameOverride, g_functionParameterTypeOverride, false);
  }
}
<|endoftext|>


<commit_before>/*
 * Copyright (c) 2015 Cryptonomex, Inc., and contributors.
 *
 * The MIT License
 *
 * 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.
 */
#pragma once

#define GRAPHENE_SYMBOL "BTS"
#define GRAPHENE_ADDRESS_PREFIX "BTS"

#define GRAPHENE_MIN_ACCOUNT_NAME_LENGTH 1
#define GRAPHENE_MAX_ACCOUNT_NAME_LENGTH 63

#define GRAPHENE_MIN_ASSET_SYMBOL_LENGTH 3
#define GRAPHENE_MAX_ASSET_SYMBOL_LENGTH 16

#define GRAPHENE_MAX_SHARE_SUPPLY int64_t(1000000000000000ll)
#define GRAPHENE_MAX_SIG_CHECK_DEPTH 2
/**
 * Don't allow the committee_members to publish a limit that would
 * make the network unable to operate.
 */
#define GRAPHENE_MIN_TRANSACTION_SIZE_LIMIT 1024
#define GRAPHENE_MIN_BLOCK_INTERVAL   1 /* seconds */
#define GRAPHENE_MAX_BLOCK_INTERVAL  30 /* seconds */

#define GRAPHENE_DEFAULT_BLOCK_INTERVAL  5 /* seconds */
#define GRAPHENE_DEFAULT_MAX_TRANSACTION_SIZE 2048
#define GRAPHENE_DEFAULT_MAX_BLOCK_SIZE  (2*1000*1000) /* < 2 MiB (less than MAX_MESSAGE_SIZE in graphene/net/config.hpp) */
#define GRAPHENE_DEFAULT_MAX_TIME_UNTIL_EXPIRATION (60*60*24) // seconds,  aka: 1 day
#define GRAPHENE_DEFAULT_MAINTENANCE_INTERVAL  (60*60*24) // seconds, aka: 1 day
#define GRAPHENE_DEFAULT_MAINTENANCE_SKIP_SLOTS 3  // number of slots to skip for maintenance interval

#define GRAPHENE_MIN_UNDO_HISTORY 10
#define GRAPHENE_MAX_UNDO_HISTORY 10000

#define GRAPHENE_MIN_BLOCK_SIZE_LIMIT (GRAPHENE_MIN_TRANSACTION_SIZE_LIMIT*5) // 5 transactions per block
#define GRAPHENE_BLOCKCHAIN_PRECISION                           uint64_t( 100000 )

#define GRAPHENE_BLOCKCHAIN_PRECISION_DIGITS                    5
/** percentage fields are fixed point with a denominator of 10,000 */
#define GRAPHENE_100_PERCENT                                    10000
#define GRAPHENE_1_PERCENT                                      (GRAPHENE_100_PERCENT/100)
/** NOTE: making this a power of 2 (say 2^15) would greatly accelerate fee calcs */
#define GRAPHENE_MAX_MARKET_FEE_PERCENT                         GRAPHENE_100_PERCENT
#define GRAPHENE_DEFAULT_FORCE_SETTLEMENT_DELAY                 (60*60*24) ///< 1 day
#define GRAPHENE_DEFAULT_FORCE_SETTLEMENT_OFFSET                0 ///< 1%
#define GRAPHENE_DEFAULT_FORCE_SETTLEMENT_MAX_VOLUME            (20* GRAPHENE_1_PERCENT) ///< 20%
#define GRAPHENE_DEFAULT_PRICE_FEED_LIFETIME                    (60*60*24) ///< 1 day
#define GRAPHENE_DEFAULT_MAX_AUTHORITY_MEMBERSHIP               10
#define GRAPHENE_DEFAULT_MAX_ASSET_WHITELIST_AUTHORITIES        10
#define GRAPHENE_DEFAULT_MAX_ASSET_FEED_PUBLISHERS              10

/**
 *  These ratios are fixed point numbers with a denominator of GRAPHENE_COLLATERAL_RATIO_DENOM, the
 *  minimum maitenance collateral is therefore 1.001x and the default
 *  maintenance ratio is 1.75x
 */
///@{
#define GRAPHENE_COLLATERAL_RATIO_DENOM                 1000
#define GRAPHENE_MIN_COLLATERAL_RATIO                   1001  ///< lower than this could result in divide by 0
#define GRAPHENE_MAX_COLLATERAL_RATIO                   32000 ///< higher than this is unnecessary and may exceed int16 storage
#define GRAPHENE_DEFAULT_MAINTENANCE_COLLATERAL_RATIO   1750 ///< Call when collateral only pays off 175% the debt
#define GRAPHENE_DEFAULT_MAX_SHORT_SQUEEZE_RATIO        1500 ///< Stop calling when collateral only pays off 150% of the debt
///@}
#define GRAPHENE_DEFAULT_MARGIN_PERIOD_SEC              (30*60*60*24)

#define GRAPHENE_DEFAULT_MIN_WITNESS_COUNT                    (11)
#define GRAPHENE_DEFAULT_MIN_COMMITTEE_MEMBER_COUNT           (11)
#define GRAPHENE_DEFAULT_MAX_WITNESSES                        (1001) // SHOULD BE ODD
#define GRAPHENE_DEFAULT_MAX_COMMITTEE                        (1001) // SHOULD BE ODD
#define GRAPHENE_DEFAULT_MAX_PROPOSAL_LIFETIME_SEC            (60*60*24*7*4) // Four weeks
#define GRAPHENE_DEFAULT_COMMITTEE_PROPOSAL_REVIEW_PERIOD_SEC (60*60*24*7*2) // Two weeks
#define GRAPHENE_DEFAULT_NETWORK_PERCENT_OF_FEE               (20*GRAPHENE_1_PERCENT)
#define GRAPHENE_DEFAULT_LIFETIME_REFERRER_PERCENT_OF_FEE     (30*GRAPHENE_1_PERCENT)
#define GRAPHENE_DEFAULT_CASHBACK_VESTING_PERIOD_SEC          (60*60*24*365) ///< 1 year
#define GRAPHENE_DEFAULT_CASHBACK_VESTING_THRESHOLD           (GRAPHENE_BLOCKCHAIN_PRECISION*int64_t(100))
#define GRAPHENE_DEFAULT_BURN_PERCENT_OF_FEE                  (20*GRAPHENE_1_PERCENT)
#define GRAPHENE_DEFAULT_MAX_ASSERT_OPCODE                    1
#define GRAPHENE_DEFAULT_FEE_LIQUIDATION_THRESHOLD            GRAPHENE_BLOCKCHAIN_PRECISION * 100;
#define GRAPHENE_DEFAULT_ACCOUNTS_PER_FEE_SCALE               1000
#define GRAPHENE_DEFAULT_ACCOUNT_FEE_SCALE_BITSHIFTS          4
#define GRAPHENE_DEFAULT_MAX_BUYBACK_MARKETS                  4

#define GRAPHENE_MAX_WORKER_NAME_LENGTH                       63

#define GRAPHENE_MAX_URL_LENGTH                               127

/**
 * every second, the fraction of burned core asset which cycles is
 * GRAPHENE_CORE_ASSET_CYCLE_RATE / (1 << GRAPHENE_CORE_ASSET_CYCLE_RATE_BITS)
 */
#define GRAPHENE_CORE_ASSET_CYCLE_RATE                        17
#define GRAPHENE_CORE_ASSET_CYCLE_RATE_BITS                   32

#define GRAPHENE_DEFAULT_WITNESS_PAY_PER_BLOCK            (GRAPHENE_BLOCKCHAIN_PRECISION * int64_t( 10) )
#define GRAPHENE_DEFAULT_WITNESS_PAY_VESTING_SECONDS      (60*60*24)
#define GRAPHENE_DEFAULT_WORKER_BUDGET_PER_DAY            (GRAPHENE_BLOCKCHAIN_PRECISION * int64_t(500) * 1000 )

#define GRAPHENE_DEFAULT_MINIMUM_FEEDS                       7

#define GRAPHENE_RECENTLY_MISSED_COUNT_INCREMENT             4
#define GRAPHENE_RECENTLY_MISSED_COUNT_DECREMENT             3

#define GRAPHENE_CURRENT_DB_VERSION                          "BTS2.181221"

#define GRAPHENE_IRREVERSIBLE_THRESHOLD                      (70 * GRAPHENE_1_PERCENT)

/**
 *  Reserved Account IDs with special meaning
 */
///@{
/// Represents the current committee members, two-week review period
#define GRAPHENE_COMMITTEE_ACCOUNT (graphene::chain::account_id_type(0))
/// Represents the current witnesses
#define GRAPHENE_WITNESS_ACCOUNT (graphene::chain::account_id_type(1))
/// Represents the current committee members
#define GRAPHENE_RELAXED_COMMITTEE_ACCOUNT (graphene::chain::account_id_type(2))
/// Represents the canonical account with NO authority (nobody can access funds in null account)
#define GRAPHENE_NULL_ACCOUNT (graphene::chain::account_id_type(3))
/// Represents the canonical account with WILDCARD authority (anybody can access funds in temp account)
#define GRAPHENE_TEMP_ACCOUNT (graphene::chain::account_id_type(4))
/// Represents the canonical account for specifying you will vote directly (as opposed to a proxy)
#define GRAPHENE_PROXY_TO_SELF_ACCOUNT (graphene::chain::account_id_type(5))
/// Sentinel value used in the scheduler.
#define GRAPHENE_NULL_WITNESS (graphene::chain::witness_id_type(0))
///@}

#define GRAPHENE_FBA_STEALTH_DESIGNATED_ASSET (asset_id_type(743))

#define GRAPHENE_MAX_NESTED_OBJECTS (200)
<commit_msg>bump database in hardfork<commit_after>/*
 * Copyright (c) 2015 Cryptonomex, Inc., and contributors.
 *
 * The MIT License
 *
 * 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.
 */
#pragma once

#define GRAPHENE_SYMBOL "BTS"
#define GRAPHENE_ADDRESS_PREFIX "BTS"

#define GRAPHENE_MIN_ACCOUNT_NAME_LENGTH 1
#define GRAPHENE_MAX_ACCOUNT_NAME_LENGTH 63

#define GRAPHENE_MIN_ASSET_SYMBOL_LENGTH 3
#define GRAPHENE_MAX_ASSET_SYMBOL_LENGTH 16

#define GRAPHENE_MAX_SHARE_SUPPLY int64_t(1000000000000000ll)
#define GRAPHENE_MAX_SIG_CHECK_DEPTH 2
/**
 * Don't allow the committee_members to publish a limit that would
 * make the network unable to operate.
 */
#define GRAPHENE_MIN_TRANSACTION_SIZE_LIMIT 1024
#define GRAPHENE_MIN_BLOCK_INTERVAL   1 /* seconds */
#define GRAPHENE_MAX_BLOCK_INTERVAL  30 /* seconds */

#define GRAPHENE_DEFAULT_BLOCK_INTERVAL  5 /* seconds */
#define GRAPHENE_DEFAULT_MAX_TRANSACTION_SIZE 2048
#define GRAPHENE_DEFAULT_MAX_BLOCK_SIZE  (2*1000*1000) /* < 2 MiB (less than MAX_MESSAGE_SIZE in graphene/net/config.hpp) */
#define GRAPHENE_DEFAULT_MAX_TIME_UNTIL_EXPIRATION (60*60*24) // seconds,  aka: 1 day
#define GRAPHENE_DEFAULT_MAINTENANCE_INTERVAL  (60*60*24) // seconds, aka: 1 day
#define GRAPHENE_DEFAULT_MAINTENANCE_SKIP_SLOTS 3  // number of slots to skip for maintenance interval

#define GRAPHENE_MIN_UNDO_HISTORY 10
#define GRAPHENE_MAX_UNDO_HISTORY 10000

#define GRAPHENE_MIN_BLOCK_SIZE_LIMIT (GRAPHENE_MIN_TRANSACTION_SIZE_LIMIT*5) // 5 transactions per block
#define GRAPHENE_BLOCKCHAIN_PRECISION                           uint64_t( 100000 )

#define GRAPHENE_BLOCKCHAIN_PRECISION_DIGITS                    5
/** percentage fields are fixed point with a denominator of 10,000 */
#define GRAPHENE_100_PERCENT                                    10000
#define GRAPHENE_1_PERCENT                                      (GRAPHENE_100_PERCENT/100)
/** NOTE: making this a power of 2 (say 2^15) would greatly accelerate fee calcs */
#define GRAPHENE_MAX_MARKET_FEE_PERCENT                         GRAPHENE_100_PERCENT
#define GRAPHENE_DEFAULT_FORCE_SETTLEMENT_DELAY                 (60*60*24) ///< 1 day
#define GRAPHENE_DEFAULT_FORCE_SETTLEMENT_OFFSET                0 ///< 1%
#define GRAPHENE_DEFAULT_FORCE_SETTLEMENT_MAX_VOLUME            (20* GRAPHENE_1_PERCENT) ///< 20%
#define GRAPHENE_DEFAULT_PRICE_FEED_LIFETIME                    (60*60*24) ///< 1 day
#define GRAPHENE_DEFAULT_MAX_AUTHORITY_MEMBERSHIP               10
#define GRAPHENE_DEFAULT_MAX_ASSET_WHITELIST_AUTHORITIES        10
#define GRAPHENE_DEFAULT_MAX_ASSET_FEED_PUBLISHERS              10

/**
 *  These ratios are fixed point numbers with a denominator of GRAPHENE_COLLATERAL_RATIO_DENOM, the
 *  minimum maitenance collateral is therefore 1.001x and the default
 *  maintenance ratio is 1.75x
 */
///@{
#define GRAPHENE_COLLATERAL_RATIO_DENOM                 1000
#define GRAPHENE_MIN_COLLATERAL_RATIO                   1001  ///< lower than this could result in divide by 0
#define GRAPHENE_MAX_COLLATERAL_RATIO                   32000 ///< higher than this is unnecessary and may exceed int16 storage
#define GRAPHENE_DEFAULT_MAINTENANCE_COLLATERAL_RATIO   1750 ///< Call when collateral only pays off 175% the debt
#define GRAPHENE_DEFAULT_MAX_SHORT_SQUEEZE_RATIO        1500 ///< Stop calling when collateral only pays off 150% of the debt
///@}
#define GRAPHENE_DEFAULT_MARGIN_PERIOD_SEC              (30*60*60*24)

#define GRAPHENE_DEFAULT_MIN_WITNESS_COUNT                    (11)
#define GRAPHENE_DEFAULT_MIN_COMMITTEE_MEMBER_COUNT           (11)
#define GRAPHENE_DEFAULT_MAX_WITNESSES                        (1001) // SHOULD BE ODD
#define GRAPHENE_DEFAULT_MAX_COMMITTEE                        (1001) // SHOULD BE ODD
#define GRAPHENE_DEFAULT_MAX_PROPOSAL_LIFETIME_SEC            (60*60*24*7*4) // Four weeks
#define GRAPHENE_DEFAULT_COMMITTEE_PROPOSAL_REVIEW_PERIOD_SEC (60*60*24*7*2) // Two weeks
#define GRAPHENE_DEFAULT_NETWORK_PERCENT_OF_FEE               (20*GRAPHENE_1_PERCENT)
#define GRAPHENE_DEFAULT_LIFETIME_REFERRER_PERCENT_OF_FEE     (30*GRAPHENE_1_PERCENT)
#define GRAPHENE_DEFAULT_CASHBACK_VESTING_PERIOD_SEC          (60*60*24*365) ///< 1 year
#define GRAPHENE_DEFAULT_CASHBACK_VESTING_THRESHOLD           (GRAPHENE_BLOCKCHAIN_PRECISION*int64_t(100))
#define GRAPHENE_DEFAULT_BURN_PERCENT_OF_FEE                  (20*GRAPHENE_1_PERCENT)
#define GRAPHENE_DEFAULT_MAX_ASSERT_OPCODE                    1
#define GRAPHENE_DEFAULT_FEE_LIQUIDATION_THRESHOLD            GRAPHENE_BLOCKCHAIN_PRECISION * 100;
#define GRAPHENE_DEFAULT_ACCOUNTS_PER_FEE_SCALE               1000
#define GRAPHENE_DEFAULT_ACCOUNT_FEE_SCALE_BITSHIFTS          4
#define GRAPHENE_DEFAULT_MAX_BUYBACK_MARKETS                  4

#define GRAPHENE_MAX_WORKER_NAME_LENGTH                       63

#define GRAPHENE_MAX_URL_LENGTH                               127

/**
 * every second, the fraction of burned core asset which cycles is
 * GRAPHENE_CORE_ASSET_CYCLE_RATE / (1 << GRAPHENE_CORE_ASSET_CYCLE_RATE_BITS)
 */
#define GRAPHENE_CORE_ASSET_CYCLE_RATE                        17
#define GRAPHENE_CORE_ASSET_CYCLE_RATE_BITS                   32

#define GRAPHENE_DEFAULT_WITNESS_PAY_PER_BLOCK            (GRAPHENE_BLOCKCHAIN_PRECISION * int64_t( 10) )
#define GRAPHENE_DEFAULT_WITNESS_PAY_VESTING_SECONDS      (60*60*24)
#define GRAPHENE_DEFAULT_WORKER_BUDGET_PER_DAY            (GRAPHENE_BLOCKCHAIN_PRECISION * int64_t(500) * 1000 )

#define GRAPHENE_DEFAULT_MINIMUM_FEEDS                       7

#define GRAPHENE_RECENTLY_MISSED_COUNT_INCREMENT             4
#define GRAPHENE_RECENTLY_MISSED_COUNT_DECREMENT             3

#define GRAPHENE_CURRENT_DB_VERSION                          "BTS2.190225"

#define GRAPHENE_IRREVERSIBLE_THRESHOLD                      (70 * GRAPHENE_1_PERCENT)

/**
 *  Reserved Account IDs with special meaning
 */
///@{
/// Represents the current committee members, two-week review period
#define GRAPHENE_COMMITTEE_ACCOUNT (graphene::chain::account_id_type(0))
/// Represents the current witnesses
#define GRAPHENE_WITNESS_ACCOUNT (graphene::chain::account_id_type(1))
/// Represents the current committee members
#define GRAPHENE_RELAXED_COMMITTEE_ACCOUNT (graphene::chain::account_id_type(2))
/// Represents the canonical account with NO authority (nobody can access funds in null account)
#define GRAPHENE_NULL_ACCOUNT (graphene::chain::account_id_type(3))
/// Represents the canonical account with WILDCARD authority (anybody can access funds in temp account)
#define GRAPHENE_TEMP_ACCOUNT (graphene::chain::account_id_type(4))
/// Represents the canonical account for specifying you will vote directly (as opposed to a proxy)
#define GRAPHENE_PROXY_TO_SELF_ACCOUNT (graphene::chain::account_id_type(5))
/// Sentinel value used in the scheduler.
#define GRAPHENE_NULL_WITNESS (graphene::chain::witness_id_type(0))
///@}

#define GRAPHENE_FBA_STEALTH_DESIGNATED_ASSET (asset_id_type(743))

#define GRAPHENE_MAX_NESTED_OBJECTS (200)
<|endoftext|>


<commit_before>/*
*
* Copyright 2013 Telefonica Investigacion y Desarrollo, S.A.U
*
* This file is part of Orion Context Broker.
*
* Orion Context Broker 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.
*
* Orion Context Broker 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 Orion Context Broker. If not, see http://www.gnu.org/licenses/.
*
* For those usages not covered by this license please contact with
* iot_support at tid dot es
*
* Author: Ken Zangelin
*/
#include <string>
#include <vector>

#include "logMsg/logMsg.h"
#include "logMsg/traceLevels.h"

#include "common/string.h"
#include "common/globals.h"
#include "common/tag.h"
#include "common/compileInfo.h"
#include "common/defaultValues.h"
#include "rest/HttpHeaders.h"
#include "rest/rest.h"
#include "openssl/opensslv.h"

#include "ngsi/ParseData.h"
#include "rest/ConnectionInfo.h"
#include "rapidjson/rapidjson.h"
#include "serviceRoutines/versionTreat.h"

/* ****************************************************************************
*
* version -
*/
static char versionString[30] = { 'a', 'l', 'p', 'h', 'a', 0 };

/* ****************************************************************************
*
* libVersions -
*/
std::string libVersions(void)
{
  std::string  total  = "\"libversions\": {\n";
  std::string  boost  = "     \"boost\": ";
  std::string  curl   = "     \"libcurl\": ";
  std::string  mhd    = "     \"libmicrohttpd\": ";
  std::string  ssl    = "     \"openssl\": ";
  std::string  rjson  = "     \"rapidjson\": ";

  char         mhdVersion[64];
  char*        curlVersion = curl_version();

  snprintf(mhdVersion, sizeof(mhdVersion), "0x%08x", MHD_VERSION);

  total += boost   + "\"" + BOOST_LIB_VERSION "\"" + ",\n";
  total += curl    + "\"" + curlVersion   +   "\"" + ",\n";
  total += mhd     + "\"" + mhdVersion    +   "\"" + ",\n";
  total += ssl     + "\"" + SHLIB_VERSION_NUMBER  "\"" + ",\n";
  total += rjson   + "\"" + RAPIDJSON_VERSION_STRING "\"" + "\n";

  return total;
}

/* ****************************************************************************
*
* versionSet -
*/
void versionSet(const char* version)
{
  strncpy(versionString, version, sizeof(versionString));
}

/* ****************************************************************************
*
* versionGet -
*/
char* versionGet()
{
  return versionString;
}

/* ****************************************************************************
*
* versionTreat -
*/
std::string versionTreat
(
  ConnectionInfo*            ciP,
  int                        components,
  std::vector<std::string>&  compV,
  ParseData*                 parseDataP
)
{
  if (isOriginAllowedForCORS(ciP->httpHeaders.origin))
  {
    ciP->httpHeader.push_back(HTTP_ACCESS_CONTROL_ALLOW_ORIGIN);
    // If any origin is allowed, the header is always sent with the value "*"
    if (strcmp(corsOrigin, "__ALL") == 0)
    {
      ciP->httpHeaderValue.push_back("*");
    }
    // If a specific origin is allowed, the header is only sent if the origins match
    else
    {
      ciP->httpHeaderValue.push_back(corsOrigin);
    }
    ciP->httpHeader.push_back(HTTP_ACCESS_CONTROL_EXPOSE_HEADERS);
    ciP->httpHeaderValue.push_back(CORS_EXPOSED_HEADERS);
  }

  std::string out     = "";
  std::string indent  = "";

#ifdef UNIT_TEST
  std::string uptime = "0 d, 0 h, 0 m, 0 s";
#else
  std::string uptime = parsedUptime(getTimer()->getCurrentTime() - startTime);
#endif

  out += "{\n";
  out += "\"orion\" : {\n";
  out += "  \"version\" : \"" + std::string(versionString) + "\",\n";
  out += "  \"uptime\" : \"" + std::string(uptime) + "\",\n";
  out += "  \"git_hash\" : \"" + std::string(GIT_HASH) + "\",\n";
  out += "  \"compile_time\" : \"" + std::string(COMPILE_TIME) + "\",\n";
  out += "  \"compiled_by\" : \"" + std::string(COMPILED_BY) + "\",\n";
  out += "  \"compiled_in\" : \"" + std::string(COMPILED_IN) + "\",\n";
  out += "  \"release_date\" : \"" + std::string(RELEASE_DATE) + "\",\n";
  out += "  \"doc\" : \"" + std::string(API_DOC) + "\"," "\n" + "  " + libVersions();
  out += "  }\n";
  out += "}\n";
  out += "}\n";

  ciP->httpStatusCode = SccOk;
  return out;
}
<commit_msg>Update versionTreat.cpp<commit_after>/*
*
* Copyright 2013 Telefonica Investigacion y Desarrollo, S.A.U
*
* This file is part of Orion Context Broker.
*
* Orion Context Broker 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.
*
* Orion Context Broker 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 Orion Context Broker. If not, see http://www.gnu.org/licenses/.
*
* For those usages not covered by this license please contact with
* iot_support at tid dot es
*
* Author: Ken Zangelin
*/
#include <string>
#include <vector>

#include "logMsg/logMsg.h"
#include "logMsg/traceLevels.h"

#include "common/string.h"
#include "common/globals.h"
#include "common/tag.h"
#include "common/compileInfo.h"
#include "common/defaultValues.h"
#include "rest/HttpHeaders.h"
#include "rest/rest.h"
#include "openssl/opensslv.h"

#include "ngsi/ParseData.h"
#include "rest/ConnectionInfo.h"
#include "rapidjson/rapidjson.h"
#include "serviceRoutines/versionTreat.h"

/* ****************************************************************************
*
* version -
*/
static char versionString[30] = { 'a', 'l', 'p', 'h', 'a', 0 };

/* ****************************************************************************
*
* libVersions -
*/
std::string libVersions(void)
{
  std::string  total  = "\"libversions\": {\n";
  std::string  boost  = "     \"boost\": ";
  std::string  curl   = "     \"libcurl\": ";
  std::string  mhd    = "     \"libmicrohttpd\": ";
  std::string  ssl    = "     \"openssl\": ";
  std::string  rjson  = "     \"rapidjson\": ";

  char         mhdVersion[64];
  char*        curlVersion = curl_version();

  snprintf(mhdVersion, sizeof(mhdVersion), "0x%08x", MHD_VERSION);

  total += boost   + "\"" + BOOST_LIB_VERSION "\"" + ",\n";
  total += curl    + "\"" + curlVersion   +   "\"" + ",\n";
  total += mhd     + "\"" + MHD_get_version()    +   "\"" + ",\n";
  total += ssl     + "\"" + SHLIB_VERSION_NUMBER  "\"" + ",\n";
  total += rjson   + "\"" + RAPIDJSON_VERSION_STRING "\"" + "\n";

  return total;
}

/* ****************************************************************************
*
* versionSet -
*/
void versionSet(const char* version)
{
  strncpy(versionString, version, sizeof(versionString));
}

/* ****************************************************************************
*
* versionGet -
*/
char* versionGet()
{
  return versionString;
}

/* ****************************************************************************
*
* versionTreat -
*/
std::string versionTreat
(
  ConnectionInfo*            ciP,
  int                        components,
  std::vector<std::string>&  compV,
  ParseData*                 parseDataP
)
{
  if (isOriginAllowedForCORS(ciP->httpHeaders.origin))
  {
    ciP->httpHeader.push_back(HTTP_ACCESS_CONTROL_ALLOW_ORIGIN);
    // If any origin is allowed, the header is always sent with the value "*"
    if (strcmp(corsOrigin, "__ALL") == 0)
    {
      ciP->httpHeaderValue.push_back("*");
    }
    // If a specific origin is allowed, the header is only sent if the origins match
    else
    {
      ciP->httpHeaderValue.push_back(corsOrigin);
    }
    ciP->httpHeader.push_back(HTTP_ACCESS_CONTROL_EXPOSE_HEADERS);
    ciP->httpHeaderValue.push_back(CORS_EXPOSED_HEADERS);
  }

  std::string out     = "";
  std::string indent  = "";

#ifdef UNIT_TEST
  std::string uptime = "0 d, 0 h, 0 m, 0 s";
#else
  std::string uptime = parsedUptime(getTimer()->getCurrentTime() - startTime);
#endif

  out += "{\n";
  out += "\"orion\" : {\n";
  out += "  \"version\" : \"" + std::string(versionString) + "\",\n";
  out += "  \"uptime\" : \"" + std::string(uptime) + "\",\n";
  out += "  \"git_hash\" : \"" + std::string(GIT_HASH) + "\",\n";
  out += "  \"compile_time\" : \"" + std::string(COMPILE_TIME) + "\",\n";
  out += "  \"compiled_by\" : \"" + std::string(COMPILED_BY) + "\",\n";
  out += "  \"compiled_in\" : \"" + std::string(COMPILED_IN) + "\",\n";
  out += "  \"release_date\" : \"" + std::string(RELEASE_DATE) + "\",\n";
  out += "  \"doc\" : \"" + std::string(API_DOC) + "\"," "\n" + "  " + libVersions();
  out += "  }\n";
  out += "}\n";
  out += "}\n";

  ciP->httpStatusCode = SccOk;
  return out;
}
<|endoftext|>


<commit_before>/** Copyright (C) 2015 Ultimaker - Released under terms of the AGPLv3 License */
#include "polygon.h"

#include "linearAlg2D.h" // pointLiesOnTheRightOfLine

#include "../debug.h"

namespace cura
{

bool PolygonRef::inside(Point p, bool border_result)
{
    PolygonRef thiss = *this;
    if (size() < 1)
    {
        return false;
    }

    int crossings = 0;
    Point p0 = back();
    for(unsigned int n=0; n<size(); n++)
    {
        Point p1 = thiss[n];
        // no tests unless the segment p0-p1 is at least partly at, or to right of, p.X
        short comp = LinearAlg2D::pointLiesOnTheRightOfLine(p, p0, p1);
        if (comp == 1)
        {
            crossings++;
        }
        else if (comp == 0)
        {
            return border_result;
        }
        p0 = p1;
    }
    return (crossings % 2) == 1;
}

bool Polygons::inside(Point p, bool border_result)
{
    Polygons& thiss = *this;
    if (size() < 1)
    {
        return false;
    }

    int crossings = 0;
    for (PolygonRef poly : thiss)
    {
        Point p0 = poly.back();
        for(Point& p1 : poly)
        {
            short comp = LinearAlg2D::pointLiesOnTheRightOfLine(p, p0, p1);
            if (comp == 1)
            {
                crossings++;
            }
            else if (comp == 0)
            {
                return border_result;
            }
            p0 = p1;
        }
    }
    return (crossings % 2) == 1;
}

unsigned int Polygons::findInside(Point p, bool border_result)
{
    Polygons& thiss = *this;
    if (size() < 1)
    {
        return false;
    }

    int64_t min_x[size()];
    std::fill_n(min_x, size(), std::numeric_limits<int64_t>::max());  // initialize with int.max
    int crossings[size()];
    std::fill_n(crossings, size(), 0);  // initialize with zeros

    for (unsigned int poly_idx = 0; poly_idx < size(); poly_idx++)
    {
        PolygonRef poly = thiss[poly_idx];
        Point p0 = poly.back();
        for(Point& p1 : poly)
        {
            short comp = LinearAlg2D::pointLiesOnTheRightOfLine(p, p0, p1);
            if (comp == 1)
            {
                crossings[poly_idx]++;
                int64_t x;
                if (p1.Y == p0.Y)
                {
                    x = p0.X;
                }
                else
                {
                    x = p0.X + (p1.X-p0.X) * (p.Y-p0.Y) / (p1.Y-p0.Y);
                }
                if (x < min_x[poly_idx])
                {
                    min_x[poly_idx] = x;
                }
            }
            else if (border_result && comp == 0)
            {
                return poly_idx;
            }
            p0 = p1;
        }
    }

    int64_t min_x_uneven = std::numeric_limits<int64_t>::max();
    unsigned int ret = NO_INDEX;
    unsigned int n_unevens = 0;
    for (unsigned int array_idx = 0; array_idx < size(); array_idx++)
    {
        if (crossings[array_idx] % 2 == 1)
        {
            n_unevens++;
            if (min_x[array_idx] < min_x_uneven)
            {
                min_x_uneven = min_x[array_idx];
                ret = array_idx;
            }
        }
    }
    if (n_unevens % 2 == 0) { ret = NO_INDEX; }
    return ret;
}

void PolygonRef::simplify(int smallest_line_segment_squared, int allowed_error_distance_squared){
    PolygonRef& thiss = *this;

    if (size() <= 2)
    {
        clear();
        return;
    }

    { // remove segments smaller than allowed_error_distance
    // this is neccesary in order to avoid the case where a long segment is followed by a lot of small segments would get simplified to a long segment going to the wrong end point
    //  .......                _                 _______
    // |                      /                 |
    // |     would become    /    instead of    |
    // |                    /                   |
        Point* last = &thiss.back();
        unsigned int writing_idx = 0;
        for (unsigned int poly_idx = 0; poly_idx < size(); poly_idx++)
        {
            Point& here = thiss[poly_idx];
            if (vSize2(*last - here) < smallest_line_segment_squared)
            {
                // don't add the point
            }
            else
            {
                thiss[writing_idx] = here;
                writing_idx++;
                last = &here;
            }
        }
        polygon->erase(polygon->begin() + writing_idx , polygon->end());
    }

    Point* last = &thiss[0];
    unsigned int writing_idx = 1;
    for (unsigned int poly_idx = 1; poly_idx < size(); poly_idx++)
    {
        Point& here = thiss[poly_idx];
        if ( vSize2(here-*last) < allowed_error_distance_squared )
        {
            // don't add the point to the result
            continue;
        }
        Point& next = thiss[(poly_idx+1) % size()];
        char here_is_beyond_line = 0;
        int64_t error2 = LinearAlg2D::getDist2FromLineSegment(*last, here, next, &here_is_beyond_line);
        if (here_is_beyond_line == 0 && error2 < allowed_error_distance_squared)
        {// don't add the point to the result
        } else
        {
            thiss[writing_idx] = here;
            writing_idx++;
            last = &here;
        }
    }
    polygon->erase(polygon->begin() + writing_idx , polygon->end());

    if (size() < 3)
    {
        clear();
        return;
    }

    { // handle the line segments spanning the vector end and begin
        Point* last = &thiss.back();
        Point& here = thiss[0];
        if ( vSize2(here-*last) < allowed_error_distance_squared )
        {
            remove(0);
        }
        Point& next = thiss[1];
        int64_t error2 = LinearAlg2D::getDist2FromLineSegment(*last, here, next);
        if (error2 < allowed_error_distance_squared)
        {
            remove(0);
        } else
        {
            // leave it in
        }
    }

    if (size() < 3)
    {
        clear();
        return;
    }
}

std::vector<PolygonsPart> Polygons::splitIntoParts(bool unionAll) const
{
    std::vector<PolygonsPart> ret;
    ClipperLib::Clipper clipper(clipper_init);
    ClipperLib::PolyTree resultPolyTree;
    clipper.AddPaths(polygons, ClipperLib::ptSubject, true);
    if (unionAll)
        clipper.Execute(ClipperLib::ctUnion, resultPolyTree, ClipperLib::pftNonZero, ClipperLib::pftNonZero);
    else
        clipper.Execute(ClipperLib::ctUnion, resultPolyTree);

    splitIntoParts_processPolyTreeNode(&resultPolyTree, ret);
    return ret;
}

void Polygons::splitIntoParts_processPolyTreeNode(ClipperLib::PolyNode* node, std::vector<PolygonsPart>& ret) const
{
    for(int n=0; n<node->ChildCount(); n++)
    {
        ClipperLib::PolyNode* child = node->Childs[n];
        PolygonsPart part;
        part.add(child->Contour);
        for(int i=0; i<child->ChildCount(); i++)
        {
            part.add(child->Childs[i]->Contour);
            splitIntoParts_processPolyTreeNode(child->Childs[i], ret);
        }
        ret.push_back(part);
    }
}

unsigned int PartsView::getPartContaining(unsigned int poly_idx, unsigned int* boundary_poly_idx)
{
    PartsView& partsView = *this;
    for (unsigned int part_idx_now = 0; part_idx_now < partsView.size(); part_idx_now++)
    {
        std::vector<unsigned int>& partView = partsView[part_idx_now];
        if (partView.size() == 0) { continue; }
        std::vector<unsigned int>::iterator result = std::find(partView.begin(), partView.end(), poly_idx);
        if (result != partView.end())
        {
            if (boundary_poly_idx) { *boundary_poly_idx = partView[0]; }
            return part_idx_now;
        }
    }
    return NO_INDEX;
}

PolygonsPart PartsView::assemblePart(unsigned int part_idx)
{
    PartsView& partsView = *this;
    PolygonsPart ret;
    if (part_idx != NO_INDEX)
    {
        for (unsigned int poly_idx_ff : partsView[part_idx])
        {
            ret.add(polygons[poly_idx_ff]);
        }
    }
    return ret;
}

PolygonsPart PartsView::assemblePartContaining(unsigned int poly_idx, unsigned int* boundary_poly_idx)
{
    PolygonsPart ret;
    unsigned int part_idx = getPartContaining(poly_idx, boundary_poly_idx);
    if (part_idx != NO_INDEX)
    {
        return assemblePart(part_idx);
    }
    return ret;
}

PartsView Polygons::splitIntoPartsView(bool unionAll)
{
    Polygons reordered;
    PartsView partsView(*this);
    ClipperLib::Clipper clipper(clipper_init);
    ClipperLib::PolyTree resultPolyTree;
    clipper.AddPaths(polygons, ClipperLib::ptSubject, true);
    if (unionAll)
        clipper.Execute(ClipperLib::ctUnion, resultPolyTree, ClipperLib::pftNonZero, ClipperLib::pftNonZero);
    else
        clipper.Execute(ClipperLib::ctUnion, resultPolyTree);

    splitIntoPartsView_processPolyTreeNode(partsView, reordered, &resultPolyTree);

    (*this) = reordered;
    return partsView;
}

void Polygons::splitIntoPartsView_processPolyTreeNode(PartsView& partsView, Polygons& reordered, ClipperLib::PolyNode* node)
{
    for(int n=0; n<node->ChildCount(); n++)
    {
        ClipperLib::PolyNode* child = node->Childs[n];
        partsView.emplace_back();
        unsigned int pos = partsView.size() - 1;
        partsView[pos].push_back(reordered.size());
        reordered.add(child->Contour);
        for(int i = 0; i < child->ChildCount(); i++)
        {
            partsView[pos].push_back(reordered.size());
            reordered.add(child->Childs[i]->Contour);
            splitIntoPartsView_processPolyTreeNode(partsView, reordered, child->Childs[i]);
        }
    }
}

}//namespace cura
<commit_msg>fix: erase with impossible iterator when trying to simplify an empty polygon (CURA-1430)<commit_after>/** Copyright (C) 2015 Ultimaker - Released under terms of the AGPLv3 License */
#include "polygon.h"

#include "linearAlg2D.h" // pointLiesOnTheRightOfLine

#include "../debug.h"

namespace cura
{

bool PolygonRef::inside(Point p, bool border_result)
{
    PolygonRef thiss = *this;
    if (size() < 1)
    {
        return false;
    }

    int crossings = 0;
    Point p0 = back();
    for(unsigned int n=0; n<size(); n++)
    {
        Point p1 = thiss[n];
        // no tests unless the segment p0-p1 is at least partly at, or to right of, p.X
        short comp = LinearAlg2D::pointLiesOnTheRightOfLine(p, p0, p1);
        if (comp == 1)
        {
            crossings++;
        }
        else if (comp == 0)
        {
            return border_result;
        }
        p0 = p1;
    }
    return (crossings % 2) == 1;
}

bool Polygons::inside(Point p, bool border_result)
{
    Polygons& thiss = *this;
    if (size() < 1)
    {
        return false;
    }

    int crossings = 0;
    for (PolygonRef poly : thiss)
    {
        Point p0 = poly.back();
        for(Point& p1 : poly)
        {
            short comp = LinearAlg2D::pointLiesOnTheRightOfLine(p, p0, p1);
            if (comp == 1)
            {
                crossings++;
            }
            else if (comp == 0)
            {
                return border_result;
            }
            p0 = p1;
        }
    }
    return (crossings % 2) == 1;
}

unsigned int Polygons::findInside(Point p, bool border_result)
{
    Polygons& thiss = *this;
    if (size() < 1)
    {
        return false;
    }

    int64_t min_x[size()];
    std::fill_n(min_x, size(), std::numeric_limits<int64_t>::max());  // initialize with int.max
    int crossings[size()];
    std::fill_n(crossings, size(), 0);  // initialize with zeros

    for (unsigned int poly_idx = 0; poly_idx < size(); poly_idx++)
    {
        PolygonRef poly = thiss[poly_idx];
        Point p0 = poly.back();
        for(Point& p1 : poly)
        {
            short comp = LinearAlg2D::pointLiesOnTheRightOfLine(p, p0, p1);
            if (comp == 1)
            {
                crossings[poly_idx]++;
                int64_t x;
                if (p1.Y == p0.Y)
                {
                    x = p0.X;
                }
                else
                {
                    x = p0.X + (p1.X-p0.X) * (p.Y-p0.Y) / (p1.Y-p0.Y);
                }
                if (x < min_x[poly_idx])
                {
                    min_x[poly_idx] = x;
                }
            }
            else if (border_result && comp == 0)
            {
                return poly_idx;
            }
            p0 = p1;
        }
    }

    int64_t min_x_uneven = std::numeric_limits<int64_t>::max();
    unsigned int ret = NO_INDEX;
    unsigned int n_unevens = 0;
    for (unsigned int array_idx = 0; array_idx < size(); array_idx++)
    {
        if (crossings[array_idx] % 2 == 1)
        {
            n_unevens++;
            if (min_x[array_idx] < min_x_uneven)
            {
                min_x_uneven = min_x[array_idx];
                ret = array_idx;
            }
        }
    }
    if (n_unevens % 2 == 0) { ret = NO_INDEX; }
    return ret;
}

void PolygonRef::simplify(int smallest_line_segment_squared, int allowed_error_distance_squared){
    PolygonRef& thiss = *this;

    if (size() <= 2)
    {
        clear();
        return;
    }

    { // remove segments smaller than allowed_error_distance
    // this is neccesary in order to avoid the case where a long segment is followed by a lot of small segments would get simplified to a long segment going to the wrong end point
    //  .......                _                 _______
    // |                      /                 |
    // |     would become    /    instead of    |
    // |                    /                   |
        Point* last = &thiss.back();
        unsigned int writing_idx = 0;
        for (unsigned int poly_idx = 0; poly_idx < size(); poly_idx++)
        {
            Point& here = thiss[poly_idx];
            if (vSize2(*last - here) < smallest_line_segment_squared)
            {
                // don't add the point
            }
            else
            {
                thiss[writing_idx] = here;
                writing_idx++;
                last = &here;
            }
        }
        polygon->erase(polygon->begin() + writing_idx , polygon->end());
    }

    if (size() < 3)
    {
        clear();
        return;
    }

    Point* last = &thiss[0];
    unsigned int writing_idx = 1;
    for (unsigned int poly_idx = 1; poly_idx < size(); poly_idx++)
    {
        Point& here = thiss[poly_idx];
        if ( vSize2(here-*last) < allowed_error_distance_squared )
        {
            // don't add the point to the result
            continue;
        }
        Point& next = thiss[(poly_idx+1) % size()];
        char here_is_beyond_line = 0;
        int64_t error2 = LinearAlg2D::getDist2FromLineSegment(*last, here, next, &here_is_beyond_line);
        if (here_is_beyond_line == 0 && error2 < allowed_error_distance_squared)
        {// don't add the point to the result
        } else
        {
            thiss[writing_idx] = here;
            writing_idx++;
            last = &here;
        }
    }
    polygon->erase(polygon->begin() + writing_idx , polygon->end());

    if (size() < 3)
    {
        clear();
        return;
    }

    { // handle the line segments spanning the vector end and begin
        Point* last = &thiss.back();
        Point& here = thiss[0];
        if ( vSize2(here-*last) < allowed_error_distance_squared )
        {
            remove(0);
        }
        Point& next = thiss[1];
        int64_t error2 = LinearAlg2D::getDist2FromLineSegment(*last, here, next);
        if (error2 < allowed_error_distance_squared)
        {
            remove(0);
        } else
        {
            // leave it in
        }
    }

    if (size() < 3)
    {
        clear();
        return;
    }
}

std::vector<PolygonsPart> Polygons::splitIntoParts(bool unionAll) const
{
    std::vector<PolygonsPart> ret;
    ClipperLib::Clipper clipper(clipper_init);
    ClipperLib::PolyTree resultPolyTree;
    clipper.AddPaths(polygons, ClipperLib::ptSubject, true);
    if (unionAll)
        clipper.Execute(ClipperLib::ctUnion, resultPolyTree, ClipperLib::pftNonZero, ClipperLib::pftNonZero);
    else
        clipper.Execute(ClipperLib::ctUnion, resultPolyTree);

    splitIntoParts_processPolyTreeNode(&resultPolyTree, ret);
    return ret;
}

void Polygons::splitIntoParts_processPolyTreeNode(ClipperLib::PolyNode* node, std::vector<PolygonsPart>& ret) const
{
    for(int n=0; n<node->ChildCount(); n++)
    {
        ClipperLib::PolyNode* child = node->Childs[n];
        PolygonsPart part;
        part.add(child->Contour);
        for(int i=0; i<child->ChildCount(); i++)
        {
            part.add(child->Childs[i]->Contour);
            splitIntoParts_processPolyTreeNode(child->Childs[i], ret);
        }
        ret.push_back(part);
    }
}

unsigned int PartsView::getPartContaining(unsigned int poly_idx, unsigned int* boundary_poly_idx)
{
    PartsView& partsView = *this;
    for (unsigned int part_idx_now = 0; part_idx_now < partsView.size(); part_idx_now++)
    {
        std::vector<unsigned int>& partView = partsView[part_idx_now];
        if (partView.size() == 0) { continue; }
        std::vector<unsigned int>::iterator result = std::find(partView.begin(), partView.end(), poly_idx);
        if (result != partView.end())
        {
            if (boundary_poly_idx) { *boundary_poly_idx = partView[0]; }
            return part_idx_now;
        }
    }
    return NO_INDEX;
}

PolygonsPart PartsView::assemblePart(unsigned int part_idx)
{
    PartsView& partsView = *this;
    PolygonsPart ret;
    if (part_idx != NO_INDEX)
    {
        for (unsigned int poly_idx_ff : partsView[part_idx])
        {
            ret.add(polygons[poly_idx_ff]);
        }
    }
    return ret;
}

PolygonsPart PartsView::assemblePartContaining(unsigned int poly_idx, unsigned int* boundary_poly_idx)
{
    PolygonsPart ret;
    unsigned int part_idx = getPartContaining(poly_idx, boundary_poly_idx);
    if (part_idx != NO_INDEX)
    {
        return assemblePart(part_idx);
    }
    return ret;
}

PartsView Polygons::splitIntoPartsView(bool unionAll)
{
    Polygons reordered;
    PartsView partsView(*this);
    ClipperLib::Clipper clipper(clipper_init);
    ClipperLib::PolyTree resultPolyTree;
    clipper.AddPaths(polygons, ClipperLib::ptSubject, true);
    if (unionAll)
        clipper.Execute(ClipperLib::ctUnion, resultPolyTree, ClipperLib::pftNonZero, ClipperLib::pftNonZero);
    else
        clipper.Execute(ClipperLib::ctUnion, resultPolyTree);

    splitIntoPartsView_processPolyTreeNode(partsView, reordered, &resultPolyTree);

    (*this) = reordered;
    return partsView;
}

void Polygons::splitIntoPartsView_processPolyTreeNode(PartsView& partsView, Polygons& reordered, ClipperLib::PolyNode* node)
{
    for(int n=0; n<node->ChildCount(); n++)
    {
        ClipperLib::PolyNode* child = node->Childs[n];
        partsView.emplace_back();
        unsigned int pos = partsView.size() - 1;
        partsView[pos].push_back(reordered.size());
        reordered.add(child->Contour);
        for(int i = 0; i < child->ChildCount(); i++)
        {
            partsView[pos].push_back(reordered.size());
            reordered.add(child->Childs[i]->Contour);
            splitIntoPartsView_processPolyTreeNode(partsView, reordered, child->Childs[i]);
        }
    }
}

}//namespace cura
<|endoftext|>