<commit_before>#ifndef RESOLVER_DATA_TYPE_HPP
#define RESOLVER_DATA_TYPE_HPP

#include <cstdint>
#include <cmath>
#include <utility>
#include <vector>
#include <queue>
#include <unordered_set>
#include <boost/noncopyable.hpp>
#include <boost/format.hpp>
#include <boost/functional/hash/extensions.hpp>
#include <opencv2/core/core.hpp>

enum struct AllDirection { Same, Up, UpperRight, Right, DownerRight, Down, DownerLeft, Left, UpperLeft };

struct point_type
{
    int x;
    int y;

    inline std::string const str() const
    {
        return ( boost::format("(%1%,%2%)") % this->x % this->y ).str();
    }
    inline uint16_t num() const
    {
        return this->x * 16 + this->y;
    }

    friend inline bool operator== (point_type const& lhs, point_type const& rhs)
    {
        return lhs.x == rhs.x && lhs.y == rhs.y;
    }
    friend inline point_type const operator- (point_type const& lhs, point_type const& rhs)
    {
        return point_type{lhs.x - rhs.x, lhs.y - rhs.y};
    }
    friend inline point_type const operator+ (point_type const& lhs, point_type const& rhs)
    {
        return point_type{lhs.x + rhs.x, lhs.y + rhs.y};
    }

    inline int manhattan(point_type const& other) const
    {
        return std::abs(this->x - other.x) + std::abs(this->y - other.y);
    }
    template<class T = double>
    inline T euclid(point_type const& other) const
    {
        return std::sqrt<T>(
            std::pow<T>(this->x - other.x, 2) +
            std::pow<T>(this->y - other.y, 2)
            );
    }

    inline point_type const up() const
    {
        return point_type{this->x, this->y - 1};
    }
    inline point_type const right() const
    {
        return point_type{this->x + 1, this->y};
    }
    inline point_type const down() const
    {
        return point_type{this->x, this->y + 1};
    }
    inline point_type const left() const
    {
        return point_type{this->x - 1, this->y};
    }

    inline AllDirection direction(point_type const& point)
    {
        point_type diff = *this - point;
        if (diff.x < 0) {
            if (diff.y < 0) {
                return AllDirection::DownerRight;
            } else if (diff.y > 0) {
                return AllDirection::UpperRight;
            } else {
                return AllDirection::Right;
            }
        } else if (diff.x > 0) {
            if (diff.y < 0) {
                return AllDirection::DownerLeft;
            } else if (diff.y > 0) {
                return AllDirection::UpperLeft;
            } else {
                return AllDirection::Left;
            }
        } else {
            if (diff.y < 0) {
                return AllDirection::Down;
            } else if (diff.y > 0) {
                return AllDirection::Up;
            } else {
                return AllDirection::Same;
            }
        }
    }

    friend std::size_t hash_value(point_type const& point)
    {
        std::size_t seed = 0;
        boost::hash_combine(seed, point.x);
        boost::hash_combine(seed, point.y);
        return seed;
    }
};

typedef cv::Vec3b                            pixel_type;
typedef std::vector<uint8_t>                 unfold_image_type;
typedef cv::Mat_<cv::Vec3b>                  image_type;

// [i][j]の位置に分割された画像(cv::Mat_<cv::Vec3b>)が入っている．
typedef std::vector<std::vector<image_type>> split_image_type;

struct question_data : private boost::noncopyable
{
    int problem_id;
    std::string player_id;

    std::pair<int,int> size;
    int selectable;
    int cost_select;
    int cost_change;
    std::vector<std::vector<point_type>> block;

    question_data(
        int const problem_id,
        std::string const& player_id,
        std::pair<int,int> const& size,
        int const selectable,
        int const cost_select,
        int const cost_change,
        std::vector<std::vector<point_type>> const& block
        )
        : problem_id(problem_id), player_id(player_id), size(size), selectable(selectable), cost_select(cost_select), cost_change(cost_change), block(block)
    {
    }

    question_data(question_data&& other)
    {
        *this = std::move(other);
    }
    question_data& operator=(question_data&& other)
    {
        this->problem_id  = other.problem_id;
        this->player_id   = other.player_id;
        this->size        = std::move(other.size);
        this->selectable  = other.selectable;
        this->cost_select = other.cost_select;
        this->cost_change = other.cost_change;
        this->block       = std::move(other.block);
        return *this;
    }

    question_data clone() const
    {
        return question_data{
            problem_id,
            player_id,
            size,
            selectable,
            cost_select,
            cost_change,
            block
        };
    }
};

struct question_raw_data : private boost::noncopyable
{
    std::pair<int,int> split_num; // x * y
    int selectable_num;
    std::pair<int,int> cost; // 選択コスト / 交換コスト
    std::pair<int,int> size; // x * y
    int max_brightness; // 最大輝度
    image_type pixels;

    question_raw_data()
    {
    }
    question_raw_data(question_raw_data&& other)
    {
        *this = std::move(other);
    }
    question_raw_data& operator=(question_raw_data&& other)
    {
        this->split_num      = std::move(other.split_num);
        this->selectable_num = other.selectable_num;
        this->cost           = std::move(other.cost);
        this->size           = std::move(other.size);
        this->max_brightness = other.max_brightness;
        this->pixels         = std::move(other.pixels);
        return *this;
    }
};

// 斜め方向を表す列挙型
enum struct DiagonalDirection { UpperRight, DownerRight, DownerLeft, UpperLeft };

// 水平垂直方向を表す列挙型
enum struct HVDirection { Up, Right, Down, Left };

// 八方を表す列挙型
//enum struct AllDirection { Same, Up, UpperRight, Right, DownerRight, Down, DownerLeft, Left, UpperLeft };

inline char direction_char(HVDirection const& d)
{
    return "URDL"[static_cast<int>(d)];
}

struct answer_line
{
    point_type select;
    std::vector<HVDirection> change_list;
};
struct answer_type
{
    std::vector<answer_line> list;

    std::string const& str() const
    {
        static std::string answer_string;

        answer_string.erase(answer_string.begin(), answer_string.end());
        for (auto step : list) {
            answer_string += (boost::format("%1$02X") % step.select.num()).str();
            answer_string.push_back('\n');
            for (auto direction : step.change_list) {
                answer_string.push_back(direction_char(direction));
            }
            answer_string.push_back('\n');
        }

        return answer_string;
    }
};

struct step_type {
    answer_type answer;
    point_type selecting_cur;
    std::vector<std::vector<point_type>> matrix;

    friend bool operator== (step_type const& lhs, step_type const& rhs)
    {
        return lhs.matrix == rhs.matrix;
    }
};

template<class T>
struct direction_type
{
    // 所謂CSSなどの順番に記述
    T up;
    T right;
    T down;
    T left;
};

// ostream に吐けると便利だよね
template<typename CharT, typename Traits>
std::basic_ostream<CharT, Traits>&
operator<< (std::basic_ostream<CharT, Traits>& os, point_type const& point)
{
    os << point.str();
    return os;
}

//sort_algorithm
typedef std::vector<std::vector<std::vector<std::vector<direction_type<uint64_t>>>>> compared_type;
typedef std::vector<std::vector<direction_type<point_type>>> adjacent_type;

namespace std
{
    template <>
    struct hash<step_type>
    {
        std::size_t operator() (step_type const& step) const
        {
            std::size_t result;
            for (auto row : step.matrix) {
                for (auto point : row) {
                    boost::hash_combine(result, point);
                }
            }
            return result;
        }
    };

    template <>
    struct hash<point_type>
    {
        std::size_t operator() (point_type const& point) const
        {
            return hash_value(point);
        }
    };
}

#endif
<commit_msg>不要になった列挙型の削除<commit_after>#ifndef RESOLVER_DATA_TYPE_HPP
#define RESOLVER_DATA_TYPE_HPP

#include <cstdint>
#include <cmath>
#include <utility>
#include <vector>
#include <queue>
#include <unordered_set>
#include <boost/noncopyable.hpp>
#include <boost/format.hpp>
#include <boost/functional/hash/extensions.hpp>
#include <opencv2/core/core.hpp>

enum struct AllDirection { Same, Up, UpperRight, Right, DownerRight, Down, DownerLeft, Left, UpperLeft };

struct point_type
{
    int x;
    int y;

    inline std::string const str() const
    {
        return ( boost::format("(%1%,%2%)") % this->x % this->y ).str();
    }
    inline uint16_t num() const
    {
        return this->x * 16 + this->y;
    }

    friend inline bool operator== (point_type const& lhs, point_type const& rhs)
    {
        return lhs.x == rhs.x && lhs.y == rhs.y;
    }
    friend inline point_type const operator- (point_type const& lhs, point_type const& rhs)
    {
        return point_type{lhs.x - rhs.x, lhs.y - rhs.y};
    }
    friend inline point_type const operator+ (point_type const& lhs, point_type const& rhs)
    {
        return point_type{lhs.x + rhs.x, lhs.y + rhs.y};
    }

    inline int manhattan(point_type const& other) const
    {
        return std::abs(this->x - other.x) + std::abs(this->y - other.y);
    }
    template<class T = double>
    inline T euclid(point_type const& other) const
    {
        return std::sqrt<T>(
            std::pow<T>(this->x - other.x, 2) +
            std::pow<T>(this->y - other.y, 2)
            );
    }

    inline point_type const up() const
    {
        return point_type{this->x, this->y - 1};
    }
    inline point_type const right() const
    {
        return point_type{this->x + 1, this->y};
    }
    inline point_type const down() const
    {
        return point_type{this->x, this->y + 1};
    }
    inline point_type const left() const
    {
        return point_type{this->x - 1, this->y};
    }

    inline AllDirection direction(point_type const& point)
    {
        point_type diff = *this - point;
        if (diff.x < 0) {
            if (diff.y < 0) {
                return AllDirection::DownerRight;
            } else if (diff.y > 0) {
                return AllDirection::UpperRight;
            } else {
                return AllDirection::Right;
            }
        } else if (diff.x > 0) {
            if (diff.y < 0) {
                return AllDirection::DownerLeft;
            } else if (diff.y > 0) {
                return AllDirection::UpperLeft;
            } else {
                return AllDirection::Left;
            }
        } else {
            if (diff.y < 0) {
                return AllDirection::Down;
            } else if (diff.y > 0) {
                return AllDirection::Up;
            } else {
                return AllDirection::Same;
            }
        }
    }

    friend std::size_t hash_value(point_type const& point)
    {
        std::size_t seed = 0;
        boost::hash_combine(seed, point.x);
        boost::hash_combine(seed, point.y);
        return seed;
    }
};

typedef cv::Vec3b                            pixel_type;
typedef std::vector<uint8_t>                 unfold_image_type;
typedef cv::Mat_<cv::Vec3b>                  image_type;

// [i][j]の位置に分割された画像(cv::Mat_<cv::Vec3b>)が入っている．
typedef std::vector<std::vector<image_type>> split_image_type;

struct question_data : private boost::noncopyable
{
    int problem_id;
    std::string player_id;

    std::pair<int,int> size;
    int selectable;
    int cost_select;
    int cost_change;
    std::vector<std::vector<point_type>> block;

    question_data(
        int const problem_id,
        std::string const& player_id,
        std::pair<int,int> const& size,
        int const selectable,
        int const cost_select,
        int const cost_change,
        std::vector<std::vector<point_type>> const& block
        )
        : problem_id(problem_id), player_id(player_id), size(size), selectable(selectable), cost_select(cost_select), cost_change(cost_change), block(block)
    {
    }

    question_data(question_data&& other)
    {
        *this = std::move(other);
    }
    question_data& operator=(question_data&& other)
    {
        this->problem_id  = other.problem_id;
        this->player_id   = other.player_id;
        this->size        = std::move(other.size);
        this->selectable  = other.selectable;
        this->cost_select = other.cost_select;
        this->cost_change = other.cost_change;
        this->block       = std::move(other.block);
        return *this;
    }

    question_data clone() const
    {
        return question_data{
            problem_id,
            player_id,
            size,
            selectable,
            cost_select,
            cost_change,
            block
        };
    }
};

struct question_raw_data : private boost::noncopyable
{
    std::pair<int,int> split_num; // x * y
    int selectable_num;
    std::pair<int,int> cost; // 選択コスト / 交換コスト
    std::pair<int,int> size; // x * y
    int max_brightness; // 最大輝度
    image_type pixels;

    question_raw_data()
    {
    }
    question_raw_data(question_raw_data&& other)
    {
        *this = std::move(other);
    }
    question_raw_data& operator=(question_raw_data&& other)
    {
        this->split_num      = std::move(other.split_num);
        this->selectable_num = other.selectable_num;
        this->cost           = std::move(other.cost);
        this->size           = std::move(other.size);
        this->max_brightness = other.max_brightness;
        this->pixels         = std::move(other.pixels);
        return *this;
    }
};

// 水平垂直方向を表す列挙型
enum struct HVDirection { Up, Right, Down, Left };

inline char direction_char(HVDirection const& d)
{
    return "URDL"[static_cast<int>(d)];
}

struct answer_line
{
    point_type select;
    std::vector<HVDirection> change_list;
};
struct answer_type
{
    std::vector<answer_line> list;

    std::string const& str() const
    {
        static std::string answer_string;

        answer_string.erase(answer_string.begin(), answer_string.end());
        for (auto step : list) {
            answer_string += (boost::format("%1$02X") % step.select.num()).str();
            answer_string.push_back('\n');
            for (auto direction : step.change_list) {
                answer_string.push_back(direction_char(direction));
            }
            answer_string.push_back('\n');
        }

        return answer_string;
    }
};

struct step_type {
    answer_type answer;
    point_type selecting_cur;
    std::vector<std::vector<point_type>> matrix;

    friend bool operator== (step_type const& lhs, step_type const& rhs)
    {
        return lhs.matrix == rhs.matrix;
    }
};

template<class T>
struct direction_type
{
    // 所謂CSSなどの順番に記述
    T up;
    T right;
    T down;
    T left;
};

// ostream に吐けると便利だよね
template<typename CharT, typename Traits>
std::basic_ostream<CharT, Traits>&
operator<< (std::basic_ostream<CharT, Traits>& os, point_type const& point)
{
    os << point.str();
    return os;
}

//sort_algorithm
typedef std::vector<std::vector<std::vector<std::vector<direction_type<uint64_t>>>>> compared_type;
typedef std::vector<std::vector<direction_type<point_type>>> adjacent_type;

namespace std
{
    template <>
    struct hash<step_type>
    {
        std::size_t operator() (step_type const& step) const
        {
            std::size_t result;
            for (auto row : step.matrix) {
                for (auto point : row) {
                    boost::hash_combine(result, point);
                }
            }
            return result;
        }
    };

    template <>
    struct hash<point_type>
    {
        std::size_t operator() (point_type const& point) const
        {
            return hash_value(point);
        }
    };
}

#endif
<|endoftext|>


<commit_before>//===--- IndexerMain.cpp -----------------------------------------*- C++-*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
// clangd-indexer is a tool to gather index data (symbols, xrefs) from source.
//
//===----------------------------------------------------------------------===//

#include "index/IndexAction.h"
#include "index/Merge.h"
#include "index/Ref.h"
#include "index/Serialization.h"
#include "index/Symbol.h"
#include "index/SymbolCollector.h"
#include "clang/Tooling/CommonOptionsParser.h"
#include "clang/Tooling/Execution.h"
#include "clang/Tooling/Tooling.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Signals.h"

namespace clang {
namespace clangd {
namespace {

static llvm::cl::opt<IndexFileFormat>
    Format("format", llvm::cl::desc("Format of the index to be written"),
           llvm::cl::values(clEnumValN(IndexFileFormat::YAML, "yaml",
                                       "human-readable YAML format"),
                            clEnumValN(IndexFileFormat::RIFF, "binary",
                                       "binary RIFF format")),
           llvm::cl::init(IndexFileFormat::RIFF));

class IndexActionFactory : public tooling::FrontendActionFactory {
public:
  IndexActionFactory(IndexFileIn &Result) : Result(Result) {}

  clang::FrontendAction *create() override {
    SymbolCollector::Options Opts;
    return createStaticIndexingAction(
               Opts,
               [&](SymbolSlab S) {
                 // Merge as we go.
                 std::lock_guard<std::mutex> Lock(SymbolsMu);
                 for (const auto &Sym : S) {
                   if (const auto *Existing = Symbols.find(Sym.ID))
                     Symbols.insert(mergeSymbol(*Existing, Sym));
                   else
                     Symbols.insert(Sym);
                 }
               },
               [&](RefSlab S) {
                 std::lock_guard<std::mutex> Lock(SymbolsMu);
                 for (const auto &Sym : S) {
                   // No need to merge as currently all Refs are from main file.
                   for (const auto &Ref : Sym.second)
                     Refs.insert(Sym.first, Ref);
                 }
               },
               /*IncludeGraphCallback=*/nullptr)
        .release();
  }

  // Awkward: we write the result in the destructor, because the executor
  // takes ownership so it's the easiest way to get our data back out.
  ~IndexActionFactory() {
    Result.Symbols = std::move(Symbols).build();
    Result.Refs = std::move(Refs).build();
  }

private:
  IndexFileIn &Result;
  std::mutex SymbolsMu;
  SymbolSlab::Builder Symbols;
  RefSlab::Builder Refs;
};

} // namespace
} // namespace clangd
} // namespace clang

int main(int argc, const char **argv) {
  llvm::sys::PrintStackTraceOnErrorSignal(argv[0]);

  const char *Overview = R"(
  Creates an index of symbol information etc in a whole project.

  Example usage for a project using CMake compile commands:

  $ clangd-indexer --executor=all-TUs compile_commands.json > clangd.dex

  Example usage for file sequence index without flags:

  $ clangd-indexer File1.cpp File2.cpp ... FileN.cpp > clangd.dex

  Note: only symbols from header files will be indexed.
  )";

  auto Executor = clang::tooling::createExecutorFromCommandLineArgs(
      argc, argv, llvm::cl::GeneralCategory, Overview);

  if (!Executor) {
    llvm::errs() << llvm::toString(Executor.takeError()) << "\n";
    return 1;
  }

  // Collect symbols found in each translation unit, merging as we go.
  clang::clangd::IndexFileIn Data;
  auto Err = Executor->get()->execute(
      llvm::make_unique<clang::clangd::IndexActionFactory>(Data));
  if (Err) {
    llvm::errs() << llvm::toString(std::move(Err)) << "\n";
  }

  // Emit collected data.
  clang::clangd::IndexFileOut Out(Data);
  Out.Format = clang::clangd::Format;
  llvm::outs() << Out;
  return 0;
}
<commit_msg>[clangd] Strip plugin arguments in clangd-indexer.<commit_after>//===--- IndexerMain.cpp -----------------------------------------*- C++-*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
// clangd-indexer is a tool to gather index data (symbols, xrefs) from source.
//
//===----------------------------------------------------------------------===//

#include "index/IndexAction.h"
#include "index/Merge.h"
#include "index/Ref.h"
#include "index/Serialization.h"
#include "index/Symbol.h"
#include "index/SymbolCollector.h"
#include "clang/Tooling/ArgumentsAdjusters.h"
#include "clang/Tooling/CommonOptionsParser.h"
#include "clang/Tooling/Execution.h"
#include "clang/Tooling/Tooling.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Signals.h"

namespace clang {
namespace clangd {
namespace {

static llvm::cl::opt<IndexFileFormat>
    Format("format", llvm::cl::desc("Format of the index to be written"),
           llvm::cl::values(clEnumValN(IndexFileFormat::YAML, "yaml",
                                       "human-readable YAML format"),
                            clEnumValN(IndexFileFormat::RIFF, "binary",
                                       "binary RIFF format")),
           llvm::cl::init(IndexFileFormat::RIFF));

class IndexActionFactory : public tooling::FrontendActionFactory {
public:
  IndexActionFactory(IndexFileIn &Result) : Result(Result) {}

  clang::FrontendAction *create() override {
    SymbolCollector::Options Opts;
    return createStaticIndexingAction(
               Opts,
               [&](SymbolSlab S) {
                 // Merge as we go.
                 std::lock_guard<std::mutex> Lock(SymbolsMu);
                 for (const auto &Sym : S) {
                   if (const auto *Existing = Symbols.find(Sym.ID))
                     Symbols.insert(mergeSymbol(*Existing, Sym));
                   else
                     Symbols.insert(Sym);
                 }
               },
               [&](RefSlab S) {
                 std::lock_guard<std::mutex> Lock(SymbolsMu);
                 for (const auto &Sym : S) {
                   // No need to merge as currently all Refs are from main file.
                   for (const auto &Ref : Sym.second)
                     Refs.insert(Sym.first, Ref);
                 }
               },
               /*IncludeGraphCallback=*/nullptr)
        .release();
  }

  // Awkward: we write the result in the destructor, because the executor
  // takes ownership so it's the easiest way to get our data back out.
  ~IndexActionFactory() {
    Result.Symbols = std::move(Symbols).build();
    Result.Refs = std::move(Refs).build();
  }

private:
  IndexFileIn &Result;
  std::mutex SymbolsMu;
  SymbolSlab::Builder Symbols;
  RefSlab::Builder Refs;
};

} // namespace
} // namespace clangd
} // namespace clang

int main(int argc, const char **argv) {
  llvm::sys::PrintStackTraceOnErrorSignal(argv[0]);

  const char *Overview = R"(
  Creates an index of symbol information etc in a whole project.

  Example usage for a project using CMake compile commands:

  $ clangd-indexer --executor=all-TUs compile_commands.json > clangd.dex

  Example usage for file sequence index without flags:

  $ clangd-indexer File1.cpp File2.cpp ... FileN.cpp > clangd.dex

  Note: only symbols from header files will be indexed.
  )";

  auto Executor = clang::tooling::createExecutorFromCommandLineArgs(
      argc, argv, llvm::cl::GeneralCategory, Overview);

  if (!Executor) {
    llvm::errs() << llvm::toString(Executor.takeError()) << "\n";
    return 1;
  }

  // Collect symbols found in each translation unit, merging as we go.
  clang::clangd::IndexFileIn Data;
  auto Err = Executor->get()->execute(
      llvm::make_unique<clang::clangd::IndexActionFactory>(Data),
      clang::tooling::getStripPluginsAdjuster());
  if (Err) {
    llvm::errs() << llvm::toString(std::move(Err)) << "\n";
  }

  // Emit collected data.
  clang::clangd::IndexFileOut Out(Data);
  Out.Format = clang::clangd::Format;
  llvm::outs() << Out;
  return 0;
}
<|endoftext|>


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

#include <stan/io/json/json_data.hpp>
#include <stan/io/json/json_data_handler.hpp>
#include <stan/io/json/json_error.hpp>
#include <stan/io/json/json_handler.hpp>
#include <stan/io/json/json_parser.hpp>

void test_rtl_2_ltr(size_t idx_rtl,
                    size_t idx_ltr,
                    const std::vector<size_t>& dims) {
  stan::json::vars_map_r vars_r;
  stan::json::vars_map_i vars_i;
  stan::json::json_data_handler handler(vars_r, vars_i);
  EXPECT_TRUE(handler.is_int_ == 0 || handler.is_int_ == 1);
  size_t idx = handler.convert_offset_rtl_2_ltr(idx_rtl,dims);
  EXPECT_EQ(idx, idx_ltr);
}

void test_exception(size_t idx_rtl,
                    const std::string& exception_text,
                    const std::vector<size_t>& dims) {
  stan::json::vars_map_r vars_r;
  stan::json::vars_map_i vars_i;
  stan::json::json_data_handler handler(vars_r, vars_i);
  try {
    handler.convert_offset_rtl_2_ltr(idx_rtl,dims);
  } catch (const std::exception& e) {
    EXPECT_EQ(e.what(), exception_text);
    return;
  }
  FAIL();  // didn't throw an exception as expected.
}

TEST(ioJson,rtl_2_ltr_1) {
  std::vector<size_t> dims(1);
  dims[0] = 7;
  test_rtl_2_ltr(0,0,dims);
  test_rtl_2_ltr(1,1,dims);
  test_rtl_2_ltr(2,2,dims);
  test_rtl_2_ltr(3,3,dims);
  test_rtl_2_ltr(4,4,dims);
  test_rtl_2_ltr(5,5,dims);
  test_rtl_2_ltr(6,6,dims);
}

//  row major:
//  11 12 13 14 21 22 23 24
//  column major:
//  11 21 12 22 13 23 14 24

TEST(ioJson,rtl_2_ltr_2) {
  std::vector<size_t> dims(2);
  dims[0] = 2;
  dims[1] = 4;
  test_rtl_2_ltr(0,0,dims);
  test_rtl_2_ltr(1,2,dims);
  test_rtl_2_ltr(2,4,dims);
  test_rtl_2_ltr(3,6,dims);
  test_rtl_2_ltr(4,1,dims);
  test_rtl_2_ltr(5,3,dims);
  test_rtl_2_ltr(6,5,dims);
  test_rtl_2_ltr(7,7,dims);
}

TEST(ioJson,rtl_2_ltr_err_1) {
  std::vector<size_t> dims(1);
  dims[0] = 7;
  test_exception(7,"variable: , unexpected error",dims);
}

TEST(ioJson,rtl_2_ltr_err_2) {
  std::vector<size_t> dims(2);
  dims[0] = 2;
  dims[1] = 4;
  test_exception(8,"variable: , unexpected error",dims);
}

TEST(ioJson,rtl_2_ltr_err_3n) {
  std::vector<size_t> dims(2);
  dims[0] = 2;
  dims[1] = 4;
  test_exception(11,"variable: , unexpected error",dims);
}
<commit_msg>final testing for undefined bools, fixes #2344<commit_after>#include <gtest/gtest.h>

#include <stan/io/json/json_data.hpp>
#include <stan/io/json/json_data_handler.hpp>
#include <stan/io/json/json_error.hpp>
#include <stan/io/json/json_handler.hpp>
#include <stan/io/json/json_parser.hpp>

void test_rtl_2_ltr(size_t idx_rtl,
                    size_t idx_ltr,
                    const std::vector<size_t>& dims) {
  stan::json::vars_map_r vars_r;
  stan::json::vars_map_i vars_i;
  stan::json::json_data_handler handler(vars_r, vars_i);

  size_t idx = handler.convert_offset_rtl_2_ltr(idx_rtl,dims);
  EXPECT_EQ(idx, idx_ltr);
}

void test_exception(size_t idx_rtl,
                    const std::string& exception_text,
                    const std::vector<size_t>& dims) {
  stan::json::vars_map_r vars_r;
  stan::json::vars_map_i vars_i;
  stan::json::json_data_handler handler(vars_r, vars_i);
  try {
    handler.convert_offset_rtl_2_ltr(idx_rtl,dims);
  } catch (const std::exception& e) {
    EXPECT_EQ(e.what(), exception_text);
    return;
  }
  FAIL();  // didn't throw an exception as expected.
}

TEST(ioJson,rtl_2_ltr_1) {
  std::vector<size_t> dims(1);
  dims[0] = 7;
  test_rtl_2_ltr(0,0,dims);
  test_rtl_2_ltr(1,1,dims);
  test_rtl_2_ltr(2,2,dims);
  test_rtl_2_ltr(3,3,dims);
  test_rtl_2_ltr(4,4,dims);
  test_rtl_2_ltr(5,5,dims);
  test_rtl_2_ltr(6,6,dims);
}

//  row major:
//  11 12 13 14 21 22 23 24
//  column major:
//  11 21 12 22 13 23 14 24

TEST(ioJson,rtl_2_ltr_2) {
  std::vector<size_t> dims(2);
  dims[0] = 2;
  dims[1] = 4;
  test_rtl_2_ltr(0,0,dims);
  test_rtl_2_ltr(1,2,dims);
  test_rtl_2_ltr(2,4,dims);
  test_rtl_2_ltr(3,6,dims);
  test_rtl_2_ltr(4,1,dims);
  test_rtl_2_ltr(5,3,dims);
  test_rtl_2_ltr(6,5,dims);
  test_rtl_2_ltr(7,7,dims);
}

TEST(ioJson,rtl_2_ltr_err_1) {
  std::vector<size_t> dims(1);
  dims[0] = 7;
  test_exception(7,"variable: , unexpected error",dims);
}

TEST(ioJson,rtl_2_ltr_err_2) {
  std::vector<size_t> dims(2);
  dims[0] = 2;
  dims[1] = 4;
  test_exception(8,"variable: , unexpected error",dims);
}

TEST(ioJson,rtl_2_ltr_err_3n) {
  std::vector<size_t> dims(2);
  dims[0] = 2;
  dims[1] = 4;
  test_exception(11,"variable: , unexpected error",dims);
}
<|endoftext|>


<commit_before>// This file is part of OpenCV project.
// It is subject to the license terms in the LICENSE file found in the top-level directory
// of this distribution and at http://opencv.org/license.html.

#ifndef OPENCV_VERSION_HPP
#define OPENCV_VERSION_HPP

#define CV_VERSION_MAJOR    3
#define CV_VERSION_MINOR    4
#define CV_VERSION_REVISION 8
#define CV_VERSION_STATUS   "-pre"

#define CVAUX_STR_EXP(__A)  #__A
#define CVAUX_STR(__A)      CVAUX_STR_EXP(__A)

#define CVAUX_STRW_EXP(__A)  L ## #__A
#define CVAUX_STRW(__A)      CVAUX_STRW_EXP(__A)

#define CV_VERSION          CVAUX_STR(CV_VERSION_MAJOR) "." CVAUX_STR(CV_VERSION_MINOR) "." CVAUX_STR(CV_VERSION_REVISION) CV_VERSION_STATUS

/* old  style version constants*/
#define CV_MAJOR_VERSION    CV_VERSION_MAJOR
#define CV_MINOR_VERSION    CV_VERSION_MINOR
#define CV_SUBMINOR_VERSION CV_VERSION_REVISION

#endif // OPENCV_VERSION_HPP
<commit_msg>OpenCV release (3.4.8)<commit_after>// This file is part of OpenCV project.
// It is subject to the license terms in the LICENSE file found in the top-level directory
// of this distribution and at http://opencv.org/license.html.

#ifndef OPENCV_VERSION_HPP
#define OPENCV_VERSION_HPP

#define CV_VERSION_MAJOR    3
#define CV_VERSION_MINOR    4
#define CV_VERSION_REVISION 8
#define CV_VERSION_STATUS   ""

#define CVAUX_STR_EXP(__A)  #__A
#define CVAUX_STR(__A)      CVAUX_STR_EXP(__A)

#define CVAUX_STRW_EXP(__A)  L ## #__A
#define CVAUX_STRW(__A)      CVAUX_STRW_EXP(__A)

#define CV_VERSION          CVAUX_STR(CV_VERSION_MAJOR) "." CVAUX_STR(CV_VERSION_MINOR) "." CVAUX_STR(CV_VERSION_REVISION) CV_VERSION_STATUS

/* old  style version constants*/
#define CV_MAJOR_VERSION    CV_VERSION_MAJOR
#define CV_MINOR_VERSION    CV_VERSION_MINOR
#define CV_SUBMINOR_VERSION CV_VERSION_REVISION

#endif // OPENCV_VERSION_HPP
<|endoftext|>


<commit_before>////////////////////////////////////////////////////////////////////////////////
// The Loki Library
// Copyright (c) 2006 Peter Kmmel
// Permission to use, copy, modify, distribute and sell this software for any
//     purpose is hereby granted without fee, provided that the above copyright
//     notice appear in all copies and that both that copyright notice and this
//     permission notice appear in supporting documentation.
// The author makes no representations about the
//     suitability of this software for any purpose. It is provided "as is"
//     without express or implied warranty.
////////////////////////////////////////////////////////////////////////////////

// $Header:

#include <loki/ScopeGuard.h>

#include <vector>
#include <string>
#include <iostream>

void Decrement(int& x)
{
    --x;
}

struct UserDatabase
{
    void AddFriend(const std::string&, const std::string&)
    {
        throw 55;
    }
};

class User
{
public:
    User(UserDatabase* db) : fCount(0), pDB_(db)
    {}

    std::string GetName();

    void AddFriend(User& newFriend);
    void AddFriendGuarded(User& newFriend);

    size_t countFriends();

    int fCount;

private:
    typedef std::vector<User*> UserCont;
    UserCont friends_;
    UserDatabase* pDB_;
};

std::string User::GetName()
{
    return "A name";
}

size_t User::countFriends()
{
    return friends_.size();
}

void User::AddFriend(User& newFriend)
{
    friends_.push_back(&newFriend);
    fCount++;
    pDB_->AddFriend(GetName(), newFriend.GetName());
}

void User::AddFriendGuarded(User& newFriend)
{
    friends_.push_back(&newFriend);
    Loki::ScopeGuard guard = Loki::MakeObjGuard(friends_, &UserCont::pop_back);

    fCount++;
    Loki::ScopeGuard guardRef = Loki::MakeGuard(Decrement, Loki::ByRef(fCount));

    pDB_->AddFriend(GetName(), newFriend.GetName());
    guard.Dismiss();
    guardRef.Dismiss();
}

int main()
{
    UserDatabase db;

    User u1(&db);
    User u2(&db);

    try{ u1.AddFriend(u2); }
    catch (...){}
    std::cout << "u1 countFriends: " << u1.countFriends() << "\n";
    std::cout << "u1 fCount      : " << u1.fCount << "\n";

    try{ u2.AddFriendGuarded(u1); }
    catch (...){}
    std::cout << "u2 countFriends: " << u2.countFriends() << "\n";
    std::cout << "u2 fCount      : " << u2.fCount << "\n";

#if defined(__BORLANDC__) || defined(_MSC_VER)
    system("PAUSE");
#endif

}
<commit_msg>Fixed syntax for CVS keyword.<commit_after>////////////////////////////////////////////////////////////////////////////////
// The Loki Library
// Copyright (c) 2006 Peter Kmmel
// Permission to use, copy, modify, distribute and sell this software for any
//     purpose is hereby granted without fee, provided that the above copyright
//     notice appear in all copies and that both that copyright notice and this
//     permission notice appear in supporting documentation.
// The author makes no representations about the
//     suitability of this software for any purpose. It is provided "as is"
//     without express or implied warranty.
////////////////////////////////////////////////////////////////////////////////

// $Header$

#include <loki/ScopeGuard.h>

#include <vector>
#include <string>
#include <iostream>

void Decrement(int& x)
{
    --x;
}

struct UserDatabase
{
    void AddFriend(const std::string&, const std::string&)
    {
        throw 55;
    }
};

class User
{
public:
    User(UserDatabase* db) : fCount(0), pDB_(db)
    {}

    std::string GetName();

    void AddFriend(User& newFriend);
    void AddFriendGuarded(User& newFriend);

    size_t countFriends();

    int fCount;

private:
    typedef std::vector<User*> UserCont;
    UserCont friends_;
    UserDatabase* pDB_;
};

std::string User::GetName()
{
    return "A name";
}

size_t User::countFriends()
{
    return friends_.size();
}

void User::AddFriend(User& newFriend)
{
    friends_.push_back(&newFriend);
    fCount++;
    pDB_->AddFriend(GetName(), newFriend.GetName());
}

void User::AddFriendGuarded(User& newFriend)
{
    friends_.push_back(&newFriend);
    Loki::ScopeGuard guard = Loki::MakeObjGuard(friends_, &UserCont::pop_back);

    fCount++;
    Loki::ScopeGuard guardRef = Loki::MakeGuard(Decrement, Loki::ByRef(fCount));

    pDB_->AddFriend(GetName(), newFriend.GetName());
    guard.Dismiss();
    guardRef.Dismiss();
}

int main()
{
    UserDatabase db;

    User u1(&db);
    User u2(&db);

    try{ u1.AddFriend(u2); }
    catch (...){}
    std::cout << "u1 countFriends: " << u1.countFriends() << "\n";
    std::cout << "u1 fCount      : " << u1.fCount << "\n";

    try{ u2.AddFriendGuarded(u1); }
    catch (...){}
    std::cout << "u2 countFriends: " << u2.countFriends() << "\n";
    std::cout << "u2 fCount      : " << u2.fCount << "\n";

#if defined(__BORLANDC__) || defined(_MSC_VER)
    system("PAUSE");
#endif

}
<|endoftext|>


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

#define SUPPORT_STRINGSPLIT_EMPTY_LITERAL_IS_SPECIAL 0

#include "Support/StringSplit.h"

#include <array>
#include <forward_list>
#include <list>
#include <vector>

#include <gtest/gtest.h>

using namespace support;
using namespace support::strings;

template <class Range>
class RangeConverter
{
    Range const& R;

public:
    RangeConverter(Range const& R)
        : R(R)
    {
    }

    template <class Container>
    operator Container() const
    {
        return Container(R.begin(), R.end());
    }
};

template <class Range>
RangeConverter<Range> convert(Range const& R)
{
    return RangeConverter<Range>(R);
}

//TEST(StringSplitTest, EmptyString1)
//{
//    std::vector<StringRef> vec{ split({}, ",") };
//
//    ASSERT_EQ(vec.size(), 1);
//    EXPECT_EQ(vec[0], "");
//}
//
//TEST(StringSplitTest, EmptyString2)
//{
//    std::vector<StringRef> vec{ split("", ",") };
//
//    ASSERT_EQ(vec.size(), 1);
//    EXPECT_EQ(vec[0], "");
//}

TEST(StringSplitTest, EmptyString3)
{
    std::vector<StringRef> vec{ split({}, any_of(",")) };

    ASSERT_EQ(vec.size(), 1);
    EXPECT_EQ(vec[0], "");
}

TEST(StringSplitTest, EmptyString4)
{
    std::vector<StringRef> vec{ split("", any_of(",")) };

    ASSERT_EQ(vec.size(), 1);
    EXPECT_EQ(vec[0], "");
}

TEST(StringSplitTest, X1)
{
    std::vector<StringRef> vec{ split(",", ",") };

    ASSERT_EQ(vec.size(), 2);
    EXPECT_EQ(vec[0], "");
    EXPECT_EQ(vec[1], "");
}

TEST(StringSplitTest, X2)
{
    std::vector<StringRef> vec{ split(", ", ",") };

    ASSERT_EQ(vec.size(), 2);
    EXPECT_EQ(vec[0], "");
    EXPECT_EQ(vec[1], " ");
}

TEST(StringSplitTest, Z1)
{
    std::vector<StringRef> vec{ split("a", ",") };

    ASSERT_EQ(vec.size(), 1);
    EXPECT_EQ(vec[0], "a");
}

TEST(StringSplitTest, Z2)
{
    std::vector<StringRef> vec{ split("a,", ",") };

    ASSERT_EQ(vec.size(), 2);
    EXPECT_EQ(vec[0], "a");
    EXPECT_EQ(vec[1], "");
}

TEST(StringSplitTest, Z3)
{
    std::vector<StringRef> vec{ split("a,b", ",") };

    ASSERT_EQ(vec.size(), 2);
    EXPECT_EQ(vec[0], "a");
    EXPECT_EQ(vec[1], "b");
}

TEST(StringSplitTest, Test6)
{
    std::vector<StringRef> vec{ split("a.b-c,. d, e .f-", any_of(".,-")) };

    ASSERT_EQ(vec.size(), 8);
    EXPECT_EQ(vec[0], "a");
    EXPECT_EQ(vec[1], "b");
    EXPECT_EQ(vec[2], "c");
    EXPECT_EQ(vec[3], "");
    EXPECT_EQ(vec[4], " d");
    EXPECT_EQ(vec[5], " e ");
    EXPECT_EQ(vec[6], "f");
    EXPECT_EQ(vec[7], "");
}

TEST(StringSplitTest, Test6_1)
{
    std::vector<StringRef> vec{ split("-a-b-c-", "-") };

    ASSERT_EQ(vec.size(), 5);
    EXPECT_EQ(vec[0], "");
    EXPECT_EQ(vec[1], "a");
    EXPECT_EQ(vec[2], "b");
    EXPECT_EQ(vec[3], "c");
    EXPECT_EQ(vec[4], "");
}

TEST(StringSplitTest, Test7)
{
    std::vector<StringRef> vec{ split("-a-b-c----d", "--") };

    ASSERT_EQ(vec.size(), 3);
    EXPECT_EQ(vec[0], "-a-b-c");
    EXPECT_EQ(vec[1], "");
    EXPECT_EQ(vec[2], "d");
}

TEST(StringSplitTest, Test7_1)
{
    std::vector<StringRef> vec{ split("-a-b-c----d", "-") };

    ASSERT_EQ(vec.size(), 8);
    EXPECT_EQ(vec[0], "");
    EXPECT_EQ(vec[1], "a");
    EXPECT_EQ(vec[2], "b");
    EXPECT_EQ(vec[3], "c");
    EXPECT_EQ(vec[4], "");
    EXPECT_EQ(vec[5], "");
    EXPECT_EQ(vec[6], "");
    EXPECT_EQ(vec[7], "d");
}

TEST(StringSplitTest, Test8)
{
    std::vector<StringRef> vec{ split("a-b-c-d-e", "-", 2) };

    ASSERT_EQ(vec.size(), 2);
    EXPECT_EQ(vec[0], "a");
    EXPECT_EQ(vec[1], "b");
}

TEST(StringSplitTest, EmptySepLiteral)
{
    std::vector<StringRef> vec{ split("abc", "") };

#if !defined(SUPPORT_STRINGSPLIT_EMPTY_LITERAL_IS_SPECIAL) || (SUPPORT_STRINGSPLIT_EMPTY_LITERAL_IS_SPECIAL == 0)
    ASSERT_EQ(vec.size(), 1);
    EXPECT_EQ(vec[0], "abc");
#else
    ASSERT_EQ(vec.size(), 3);
    EXPECT_EQ(vec[0], "a");
    EXPECT_EQ(vec[1], "b");
    EXPECT_EQ(vec[2], "c");
#endif
}

TEST(StringSplitTest, EmptySepAnyOf)
{
    std::vector<StringRef> vec{ split("abc", any_of("")) };

    ASSERT_EQ(vec.size(), 1);
    EXPECT_EQ(vec[0], "abc");
}

TEST(StringSplitTest, Iterator)
{
    auto I = split("a,b,c,d", ",");
    auto E = I.end();

    std::vector<StringRef> vec;

    for (; I != E; ++I)
    {
        vec.push_back(*I);
    }

    ASSERT_EQ(vec.size(), 4);
    EXPECT_EQ(vec[0], "a");
    EXPECT_EQ(vec[1], "b");
    EXPECT_EQ(vec[2], "c");
    EXPECT_EQ(vec[3], "d");
}

#if 1

#include <boost/range/adaptor/filtered.hpp>
#include <boost/range/adaptor/transformed.hpp>
#include <boost/range/algorithm.hpp>

TEST(StringSplitTest, AdaptorsTransformed)
{
    using namespace boost::adaptors;

    struct AppendX
    {
        std::string operator ()(StringRef Str) const {
            return Str + "+x";
        }
    };

    std::vector<std::string> vec
        = convert(split("a,b,c,d", ",") | transformed(AppendX()));

    ASSERT_EQ(vec.size(), 4);
    EXPECT_EQ(vec[0], "a+x");
    EXPECT_EQ(vec[1], "b+x");
    EXPECT_EQ(vec[2], "c+x");
    EXPECT_EQ(vec[3], "d+x");
}

TEST(StringSplitTest, AdaptorsFiltered)
{
    using namespace boost::adaptors;

    struct SkipEmpty
    {
        bool operator ()(StringRef Str) const {
            return !Str.empty();
        }
    };

    std::vector<std::string> vec
        = convert(split("a,,,b,,,c,,,d,,,", ",") | filtered(SkipEmpty()));

    ASSERT_EQ(vec.size(), 4);
    EXPECT_EQ(vec[0], "a");
    EXPECT_EQ(vec[1], "b");
    EXPECT_EQ(vec[2], "c");
    EXPECT_EQ(vec[3], "d");
}

#endif
<commit_msg>Compile with VC12<commit_after>// This file is distributed under the MIT license.
// See the LICENSE file for details.

#define SUPPORT_STRINGSPLIT_EMPTY_LITERAL_IS_SPECIAL 0

#include "Support/StringSplit.h"

#include <array>
#include <forward_list>
#include <list>
#include <vector>

#include <gtest/gtest.h>

using namespace support;
using namespace support::strings;

template <class Range>
class RangeConverter
{
    Range const& R;

public:
    RangeConverter(Range const& R)
        : R(R)
    {
    }

    template <class Container>
    operator Container() const
    {
        return Container(R.begin(), R.end());
    }
};

template <class Range>
RangeConverter<Range> convert(Range const& R)
{
    return RangeConverter<Range>(R);
}

TEST(StringSplitTest, EmptyString1)
{
    auto vec = std::vector<StringRef>(split({}, ","));

    ASSERT_EQ(vec.size(), 1);
    EXPECT_EQ(vec[0], "");
}

TEST(StringSplitTest, EmptyString2)
{
    auto vec = std::vector<StringRef>(split("", ","));

    ASSERT_EQ(vec.size(), 1);
    EXPECT_EQ(vec[0], "");
}

TEST(StringSplitTest, EmptyString3)
{
    auto vec = std::vector<StringRef>(split({}, any_of(",")));

    ASSERT_EQ(vec.size(), 1);
    EXPECT_EQ(vec[0], "");
}

TEST(StringSplitTest, EmptyString4)
{
    auto vec = std::vector<StringRef>(split("", any_of(",")));

    ASSERT_EQ(vec.size(), 1);
    EXPECT_EQ(vec[0], "");
}

TEST(StringSplitTest, X1)
{
    auto vec = std::vector<StringRef>(split(",", ","));

    ASSERT_EQ(vec.size(), 2);
    EXPECT_EQ(vec[0], "");
    EXPECT_EQ(vec[1], "");
}

TEST(StringSplitTest, X2)
{
    auto vec = std::vector<StringRef>(split(", ", ","));

    ASSERT_EQ(vec.size(), 2);
    EXPECT_EQ(vec[0], "");
    EXPECT_EQ(vec[1], " ");
}

TEST(StringSplitTest, Z1)
{
    auto vec = std::vector<StringRef>(split("a", ","));

    ASSERT_EQ(vec.size(), 1);
    EXPECT_EQ(vec[0], "a");
}

TEST(StringSplitTest, Z2)
{
    auto vec = std::vector<StringRef>(split("a,", ","));

    ASSERT_EQ(vec.size(), 2);
    EXPECT_EQ(vec[0], "a");
    EXPECT_EQ(vec[1], "");
}

TEST(StringSplitTest, Z3)
{
    auto vec = std::vector<StringRef>(split("a,b", ","));

    ASSERT_EQ(vec.size(), 2);
    EXPECT_EQ(vec[0], "a");
    EXPECT_EQ(vec[1], "b");
}

TEST(StringSplitTest, Test6)
{
    auto vec = std::vector<StringRef>(split("a.b-c,. d, e .f-", any_of(".,-")));

    ASSERT_EQ(vec.size(), 8);
    EXPECT_EQ(vec[0], "a");
    EXPECT_EQ(vec[1], "b");
    EXPECT_EQ(vec[2], "c");
    EXPECT_EQ(vec[3], "");
    EXPECT_EQ(vec[4], " d");
    EXPECT_EQ(vec[5], " e ");
    EXPECT_EQ(vec[6], "f");
    EXPECT_EQ(vec[7], "");
}

TEST(StringSplitTest, Test6_1)
{
    auto vec = std::vector<StringRef>(split("-a-b-c-", "-"));

    ASSERT_EQ(vec.size(), 5);
    EXPECT_EQ(vec[0], "");
    EXPECT_EQ(vec[1], "a");
    EXPECT_EQ(vec[2], "b");
    EXPECT_EQ(vec[3], "c");
    EXPECT_EQ(vec[4], "");
}

TEST(StringSplitTest, Test7)
{
    auto vec = std::vector<StringRef>(split("-a-b-c----d", "--"));

    ASSERT_EQ(vec.size(), 3);
    EXPECT_EQ(vec[0], "-a-b-c");
    EXPECT_EQ(vec[1], "");
    EXPECT_EQ(vec[2], "d");
}

TEST(StringSplitTest, Test7_1)
{
    auto vec = std::vector<StringRef>(split("-a-b-c----d", "-"));

    ASSERT_EQ(vec.size(), 8);
    EXPECT_EQ(vec[0], "");
    EXPECT_EQ(vec[1], "a");
    EXPECT_EQ(vec[2], "b");
    EXPECT_EQ(vec[3], "c");
    EXPECT_EQ(vec[4], "");
    EXPECT_EQ(vec[5], "");
    EXPECT_EQ(vec[6], "");
    EXPECT_EQ(vec[7], "d");
}

TEST(StringSplitTest, Test8)
{
    auto vec = std::vector<StringRef>(split("a-b-c-d-e", "-", 2));

    ASSERT_EQ(vec.size(), 2);
    EXPECT_EQ(vec[0], "a");
    EXPECT_EQ(vec[1], "b");
}

TEST(StringSplitTest, EmptySepLiteral)
{
    auto vec = std::vector<StringRef>(split("abc", ""));

#if !defined(SUPPORT_STRINGSPLIT_EMPTY_LITERAL_IS_SPECIAL) || (SUPPORT_STRINGSPLIT_EMPTY_LITERAL_IS_SPECIAL == 0)
    ASSERT_EQ(vec.size(), 1);
    EXPECT_EQ(vec[0], "abc");
#else
    ASSERT_EQ(vec.size(), 3);
    EXPECT_EQ(vec[0], "a");
    EXPECT_EQ(vec[1], "b");
    EXPECT_EQ(vec[2], "c");
#endif
}

TEST(StringSplitTest, EmptySepAnyOf)
{
    auto vec = std::vector<StringRef>(split("abc", any_of("")));

    ASSERT_EQ(vec.size(), 1);
    EXPECT_EQ(vec[0], "abc");
}

TEST(StringSplitTest, Iterator)
{
    auto I = split("a,b,c,d", ",");
    auto E = I.end();

    std::vector<StringRef> vec;

    for (; I != E; ++I)
    {
        vec.push_back(*I);
    }

    ASSERT_EQ(vec.size(), 4);
    EXPECT_EQ(vec[0], "a");
    EXPECT_EQ(vec[1], "b");
    EXPECT_EQ(vec[2], "c");
    EXPECT_EQ(vec[3], "d");
}

#if 0

#include <boost/range/adaptor/filtered.hpp>
#include <boost/range/adaptor/transformed.hpp>
#include <boost/range/algorithm.hpp>

TEST(StringSplitTest, AdaptorsTransformed)
{
    using namespace boost::adaptors;

    struct AppendX
    {
        std::string operator ()(StringRef Str) const {
            return Str + "+x";
        }
    };

    std::vector<std::string> vec
        = convert(split("a,b,c,d", ",") | transformed(AppendX()));

    ASSERT_EQ(vec.size(), 4);
    EXPECT_EQ(vec[0], "a+x");
    EXPECT_EQ(vec[1], "b+x");
    EXPECT_EQ(vec[2], "c+x");
    EXPECT_EQ(vec[3], "d+x");
}

TEST(StringSplitTest, AdaptorsFiltered)
{
    using namespace boost::adaptors;

    struct SkipEmpty
    {
        bool operator ()(StringRef Str) const {
            return !Str.empty();
        }
    };

    std::vector<std::string> vec
        = convert(split("a,,,b,,,c,,,d,,,", ",") | filtered(SkipEmpty()));

    ASSERT_EQ(vec.size(), 4);
    EXPECT_EQ(vec[0], "a");
    EXPECT_EQ(vec[1], "b");
    EXPECT_EQ(vec[2], "c");
    EXPECT_EQ(vec[3], "d");
}

#endif
<|endoftext|>


<commit_before>/*
 * Copyright (c) 2013, Hernan Saez
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *     * Redistributions of source code must retain the above copyright
 *       notice, this list of conditions and the following disclaimer.
 *     * Redistributions in binary form must reproduce the above copyright
 *       notice, this list of conditions and the following disclaimer in the
 *       documentation and/or other materials provided with the distribution.
 *     * Neither the name of the <organization> 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 <COPYRIGHT HOLDER> 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 "NavigationController.hpp"
#include "NavigationMeshContainer.hpp"

#include "Mathematics/Ray.hpp"
#include "Mathematics/LineSegment.hpp"
#include "Mathematics/Intersection.hpp"

#include "SceneGraph/Node.hpp"

#include "Visitors/Apply.hpp"

using namespace crimild;
using namespace crimild::navigation;

NavigationController::NavigationController( void )
{

}

NavigationController::NavigationController( NavigationMeshPtr const &mesh )
	: _navigationMesh( mesh )
{

}

NavigationController::~NavigationController( void )
{

}

void NavigationController::start( void )
{
	if ( _navigationMesh == nullptr ) {
		// No navigation mesh assigned. Find the first one in the scene
		getNode()->getRootParent()->perform( Apply( [this]( Node *node ) {
			auto nav = node->getComponent< NavigationMeshContainer >();
			if ( nav != nullptr ) {
				_navigationMesh = crimild::retain( nav->getNavigationMesh() );
			}
		}));
	}
}

Vector3f NavigationController::move( const Vector3f &from, const Vector3f &to )
{
	if ( _navigationMesh == nullptr ) {
		Log::warning( CRIMILD_CURRENT_CLASS_NAME, "No navigation mesh found" );
		return from;
	}

	NavigationCell *cell = nullptr;
	getNavigationMesh()->foreachCell( [&cell, to]( NavigationCellPtr const &c ) {
		if ( c->containsPoint( to ) ) {
			cell = crimild::get_ptr( c );
		}
	});

	if ( cell == nullptr ) {
		return from;
	}

	auto r = Ray3f( to, -Vector3f::UNIT_Y );
	const auto p = cell->getPlane();

	float t = Intersection::find( p, r );
	if ( t < 0 ) {
		r = Ray3f( to, Vector3f::UNIT_Y );
		t = Intersection::find( p, r );
		if ( t < 0 ) {
			return from;
		}
	}

	return r.getPointAt( t );
}

bool NavigationController::snap( void )
{
	// TODO: project current position into current cell and update position

	return true;
}

bool NavigationController::teleport( const Vector3f &target )
{
	auto cell = findCellForPoint( target );
	if ( cell != nullptr ) {
		setCurrentCell( cell );

		getNode()->local().setTranslate( target );
	}

	return cell != nullptr;
}

bool NavigationController::move( const Vector3f &target )
{
	// TODO: what about local/world conversion?

	auto currentCell = getCurrentCell();
	if ( currentCell == nullptr ) {
		findCurrentCell();
		currentCell = getCurrentCell();
	}

	if ( currentCell == nullptr ) {
		// not in a cell
		return false;
	}

	auto motionPath = LineSegment3f( getNode()->getLocal().getTranslate(), target );

	bool done = false;

	auto testCell = currentCell;

	NavigationCellEdge *intersectionEdge = nullptr;
	Vector3f intersectionPoint;

	// Search for the cell containing the destination point
	// or update the motion path accordingly to keep it within
	// the nav mesh
	while ( !done && ( testCell != nullptr ) && ( motionPath.getOrigin() != motionPath.getDestination() ) ) {

		// classify the motion path based on the test cell
		auto result = testCell->classifyPath( motionPath, intersectionPoint, &intersectionEdge );

		if ( result == NavigationCell::ClassificationResult::INSIDE ) {
			// We found the cell containing the destination point
			// Project that point into the cell's plane and terminate
			motionPath.setDestination( testCell->getPlane().project( motionPath.getDestination() ) );
			done = true;
		}
		else if ( result == NavigationCell::ClassificationResult::OUTSIDE ) {
			// the motion path goes outside of the test cell
			if ( intersectionEdge->getNeighbor() != nullptr ) {
				// Moving to an adjacent cell. Set motion path origin
				// to intersection point and continue with next cell
				motionPath.setOrigin( intersectionPoint );
				testCell = intersectionEdge->getNeighbor();
			}
			else {
				// We hit a wall.
				// Project the motion path on the intersection edge
				// and terminate
				motionPath = intersectionEdge->projectPath( motionPath );
				done = true;
			}
		}
		else {
			// this may happen if, for some reason, the start point of the motion path
			// lies outside of the current cell (maybe due to round errors) or it
			// coincides with one of the vertices
			// Force the motion path to start within the cell boundaries and try again
			motionPath.setOrigin( testCell->snapPoint( motionPath.getOrigin() ) );
		}
	}

	if ( testCell == nullptr ) {
		return false;
	}

	setCurrentCell( testCell );

	getNode()->local().setTranslate( motionPath.getDestination() );

	return true;
}

bool NavigationController::findCurrentCell( void )
{
	auto cell = NavigationController::findCellForPoint( getNode()->getLocal().getTranslate() );
	if ( cell != nullptr ) {
		setCurrentCell( cell );
	}

	return getCurrentCell();
}

NavigationCell *NavigationController::findCellForPoint( const Vector3f &point )
{
	NavigationCell *cell = nullptr;
	getNavigationMesh()->foreachCell( [&cell, point]( NavigationCellPtr const &c ) {
		if ( c->containsPoint( point ) ) {
			cell = crimild::get_ptr( c );
		}
	});

	return cell;
}

<commit_msg>Allow navigation teleport to work even if no valid cell is found<commit_after>/*
 * Copyright (c) 2013, Hernan Saez
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *     * Redistributions of source code must retain the above copyright
 *       notice, this list of conditions and the following disclaimer.
 *     * Redistributions in binary form must reproduce the above copyright
 *       notice, this list of conditions and the following disclaimer in the
 *       documentation and/or other materials provided with the distribution.
 *     * Neither the name of the <organization> 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 <COPYRIGHT HOLDER> 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 "NavigationController.hpp"
#include "NavigationMeshContainer.hpp"

#include "Mathematics/Ray.hpp"
#include "Mathematics/LineSegment.hpp"
#include "Mathematics/Intersection.hpp"

#include "SceneGraph/Node.hpp"

#include "Visitors/Apply.hpp"

using namespace crimild;
using namespace crimild::navigation;

NavigationController::NavigationController( void )
{

}

NavigationController::NavigationController( NavigationMeshPtr const &mesh )
	: _navigationMesh( mesh )
{

}

NavigationController::~NavigationController( void )
{

}

void NavigationController::start( void )
{
	if ( _navigationMesh == nullptr ) {
		// No navigation mesh assigned. Find the first one in the scene
		getNode()->getRootParent()->perform( Apply( [this]( Node *node ) {
			auto nav = node->getComponent< NavigationMeshContainer >();
			if ( nav != nullptr ) {
				_navigationMesh = crimild::retain( nav->getNavigationMesh() );
			}
		}));
	}
}

Vector3f NavigationController::move( const Vector3f &from, const Vector3f &to )
{
	if ( _navigationMesh == nullptr ) {
		Log::warning( CRIMILD_CURRENT_CLASS_NAME, "No navigation mesh found" );
		return from;
	}

	NavigationCell *cell = nullptr;
	getNavigationMesh()->foreachCell( [&cell, to]( NavigationCellPtr const &c ) {
		if ( c->containsPoint( to ) ) {
			cell = crimild::get_ptr( c );
		}
	});

	if ( cell == nullptr ) {
		return from;
	}

	auto r = Ray3f( to, -Vector3f::UNIT_Y );
	const auto p = cell->getPlane();

	float t = Intersection::find( p, r );
	if ( t < 0 ) {
		r = Ray3f( to, Vector3f::UNIT_Y );
		t = Intersection::find( p, r );
		if ( t < 0 ) {
			return from;
		}
	}

	return r.getPointAt( t );
}

bool NavigationController::snap( void )
{
	// TODO: project current position into current cell and update position

	return true;
}

bool NavigationController::teleport( const Vector3f &target )
{
	auto cell = findCellForPoint( target );

	setCurrentCell( cell );
	getNode()->local().setTranslate( target );

	return cell != nullptr;
}

bool NavigationController::move( const Vector3f &target )
{
	// TODO: what about local/world conversion?

	auto currentCell = getCurrentCell();
	if ( currentCell == nullptr ) {
		findCurrentCell();
		currentCell = getCurrentCell();
	}

	if ( currentCell == nullptr ) {
		// not in a cell
		return false;
	}

	auto motionPath = LineSegment3f( getNode()->getLocal().getTranslate(), target );

	bool done = false;

	auto testCell = currentCell;

	NavigationCellEdge *intersectionEdge = nullptr;
	Vector3f intersectionPoint;

	// Search for the cell containing the destination point
	// or update the motion path accordingly to keep it within
	// the nav mesh
	while ( !done && ( testCell != nullptr ) && ( motionPath.getOrigin() != motionPath.getDestination() ) ) {

		// classify the motion path based on the test cell
		auto result = testCell->classifyPath( motionPath, intersectionPoint, &intersectionEdge );

		if ( result == NavigationCell::ClassificationResult::INSIDE ) {
			// We found the cell containing the destination point
			// Project that point into the cell's plane and terminate
			motionPath.setDestination( testCell->getPlane().project( motionPath.getDestination() ) );
			done = true;
		}
		else if ( result == NavigationCell::ClassificationResult::OUTSIDE ) {
			// the motion path goes outside of the test cell
			if ( intersectionEdge->getNeighbor() != nullptr ) {
				// Moving to an adjacent cell. Set motion path origin
				// to intersection point and continue with next cell
				motionPath.setOrigin( intersectionPoint );
				testCell = intersectionEdge->getNeighbor();
			}
			else {
				// We hit a wall.
				// Project the motion path on the intersection edge
				// and terminate
				motionPath = intersectionEdge->projectPath( motionPath );
				done = true;
			}
		}
		else {
			// this may happen if, for some reason, the start point of the motion path
			// lies outside of the current cell (maybe due to round errors) or it
			// coincides with one of the vertices
			// Force the motion path to start within the cell boundaries and try again
			motionPath.setOrigin( testCell->snapPoint( motionPath.getOrigin() ) );
		}
	}

	if ( testCell == nullptr ) {
		return false;
	}

	setCurrentCell( testCell );

	getNode()->local().setTranslate( motionPath.getDestination() );

	return true;
}

bool NavigationController::findCurrentCell( void )
{
	auto cell = NavigationController::findCellForPoint( getNode()->getLocal().getTranslate() );
	if ( cell != nullptr ) {
		setCurrentCell( cell );
	}

	return getCurrentCell();
}

NavigationCell *NavigationController::findCellForPoint( const Vector3f &point )
{
	NavigationCell *cell = nullptr;
	getNavigationMesh()->foreachCell( [&cell, point]( NavigationCellPtr const &c ) {
		if ( c->containsPoint( point ) ) {
			cell = crimild::get_ptr( c );
		}
	});

	return cell;
}

<|endoftext|>


<commit_before>/*
 * Copyright (c) 2007-2008 Digital Bazaar, Inc.  All rights reserved.
 */
#include <iostream>
#include <sstream>

#include "db/rt/Exception.h"
#include "db/test/Test.h"
#include "db/test/Tester.h"
#include "db/test/TestRunner.h"
#include "db/config/ConfigManager.h"
#include "db/data/json/JsonWriter.h"

using namespace std;
using namespace db::rt;
using namespace db::test;
using namespace db::config;

void runConfigManagerTest(TestRunner& tr)
{
   tr.group("ConfigManager");

   tr.test("init");
   {
      DynamicObject expect;
      expect->setType(Map);
      ConfigManager cm;
      assertDynoCmp(cm.getConfig(), expect);
   }
   tr.passIfNoException();

   tr.test("init & clear");
   {
      DynamicObject expect;
      expect->setType(Map);
      ConfigManager cm;
      cm.clear();
      assertDynoCmp(cm.getConfig(), expect);
   }
   tr.passIfNoException();

   tr.test("1 config");
   {
      DynamicObject expect;
      expect->setType(Map);
      expect["a"] = 0;
      ConfigManager cm;
      DynamicObject a;
      a["a"] = 0;
      assert(cm.addConfig(a));
      assertNoException();
      assertDynoCmp(cm.getConfig(), expect);
   }
   tr.passIfNoException();

   tr.test("clear & 1 config");
   {
      DynamicObject expect;
      expect->setType(Map);
      expect["a"] = 0;
      ConfigManager cm;
      cm.clear();
      DynamicObject a;
      a["a"] = 0;
      assert(cm.addConfig(a));
      assertNoException();
      assertDynoCmp(cm.getConfig(), expect);
   }
   tr.passIfNoException();

   tr.test("config change");
   {
      ConfigManager cm;
      DynamicObject a;
      a["a"] = 0;
      assert(cm.addConfig(a));
      assertNoException();
      assertDynoCmp(cm.getConfig(), a);
      cm.getConfig()["a"] = 1;
      DynamicObject expect;
      expect["a"] = 1;
      assert(cm.getConfig() != a);
      assertDynoCmp(cm.getConfig(), expect);
   }
   tr.passIfNoException();

   tr.test("add");
   {
      DynamicObject expect;
      expect["a"] = 0;
      expect["b"] = 1;
      expect["c"] = 2;
      ConfigManager cm;
      DynamicObject a;
      a["a"] = 0;
      DynamicObject b;
      b["b"] = 1;
      DynamicObject c;
      c["c"] = 2;
      assert(cm.addConfig(a));
      assertNoException();
      assert(cm.addConfig(b));
      assertNoException();
      assert(cm.addConfig(c));
      assertNoException();
      assertDynoCmp(cm.getConfig(), expect);
   }
   tr.passIfNoException();

   tr.test("bad remove");
   {
      ConfigManager cm;
      assert(!cm.removeConfig(0));
      assertException();
      Exception::clearLast();
   }
   tr.passIfNoException();

   tr.test("remove");
   {
      DynamicObject expect;
      expect["a"] = 0;
      expect["b"] = 1;
      expect["c"] = 2;
      ConfigManager cm;
      DynamicObject a;
      a["a"] = 0;
      DynamicObject b;
      b["b"] = 1;
      DynamicObject c;
      c["c"] = 2;
      ConfigManager::ConfigId id;
      assert(cm.addConfig(a));
      assertNoException();
      assert(cm.addConfig(b, ConfigManager::Default, &id));
      assertNoException();
      assert(cm.addConfig(c));
      assertNoException();
      assertDynoCmp(cm.getConfig(), expect);
      DynamicObject expect2;
      expect2["a"] = 0;
      expect2["c"] = 2;
      assert(cm.removeConfig(id));
      assertDynoCmp(cm.getConfig(), expect2);
   }
   tr.passIfNoException();

   tr.test("update");
   {
      ConfigManager cm;
      DynamicObject expect;
      expect["a"] = 0;
      DynamicObject a;
      a["a"] = 0;
      assert(cm.addConfig(a));
      assertNoException();
      assertDynoCmp(cm.getConfig(), expect);
      DynamicObject expect2;
      expect2["a"] = 1;
      a["a"] = 1;
      assert(cm.getConfig() != expect2);
      cm.update();
      assertNoException();
      assertDynoCmp(cm.getConfig(), expect2);
   }
   tr.passIfNoException();

   tr.test("set");
   {
      ConfigManager cm;
      DynamicObject expect;
      expect["a"] = 0;
      DynamicObject a;
      a["a"] = 0;
      ConfigManager::ConfigId id;
      assert(cm.addConfig(a, ConfigManager::Default, &id));
      assertNoException();
      assertDynoCmp(cm.getConfig(), expect);
      DynamicObject expect2;
      expect2["b"] = 0;
      DynamicObject b;
      b["b"] = 0;
      cm.setConfig(id, b);
      assertDynoCmp(cm.getConfig(), expect2);
   }
   tr.passIfNoException();

   tr.test("get");
   {
      ConfigManager cm;
      DynamicObject expect;
      expect["a"] = 0;
      DynamicObject a;
      a["a"] = 0;
      ConfigManager::ConfigId id;
      assert(cm.addConfig(a, ConfigManager::Default, &id));
      assertNoException();
      assertDynoCmp(cm.getConfig(), expect);
      DynamicObject b;
      assert(cm.getConfig(id, b));
      assertDynoCmp(b, expect);
   }
   tr.passIfNoException();

   tr.test("map changes");
   {
      ConfigManager cm;
      DynamicObject a;
      a["a"] = 0;
      a["b"] = 0;
      assert(cm.addConfig(a));
      assertNoException();
      cm.getConfig()["a"] = 1;
      DynamicObject expect;
      expect["a"] = 1;
      DynamicObject changes;
      cm.getChanges(changes);
      assertDynoCmp(changes, expect);
   }
   tr.passIfNoException();

   tr.test("deep map changes");
   {
      ConfigManager cm;
      DynamicObject a;
      a["a"]["b"] = 0;
      a["a"]["c"] = 0;
      assert(cm.addConfig(a));
      assertNoException();
      cm.getConfig()["a"]["c"] = 1;
      cm.getConfig()["d"] = 0;
      DynamicObject expect;
      expect["a"]["c"] = 1;
      expect["d"] = 0;
      DynamicObject changes;
      cm.getChanges(changes);
      assertDynoCmp(changes, expect);
   }
   tr.passIfNoException();

   tr.test("array changes");
   {
      ConfigManager cm;
      DynamicObject a;
      a[0] = 10;
      a[1] = 11;
      a[2] = 12;
      assert(cm.addConfig(a));
      assertNoException();
      cm.getConfig()[1] = 21;
      DynamicObject expect;
      expect[0] = "__default__";
      expect[1] = 21;
      expect[2] = "__default__";
      DynamicObject changes;
      cm.getChanges(changes);
      assertDynoCmp(changes, expect);
   }
   tr.passIfNoException();

   tr.test("bigger array changes");
   {
      ConfigManager cm;
      DynamicObject a;
      a[0] = 10;
      a[1] = 11;
      assert(cm.addConfig(a));
      assertNoException();
      cm.getConfig()[2] = 22;
      DynamicObject expect;
      expect[0] = "__default__";
      expect[1] = "__default__";
      expect[2] = 22;
      DynamicObject changes;
      cm.getChanges(changes);
      assertDynoCmp(changes, expect);
   }
   tr.passIfNoException();

   tr.test("system vs user changes");
   {
      ConfigManager cm;

      // system
      DynamicObject a;
      a[0] = 10;
      a[1] = 11;
      assert(cm.addConfig(a, ConfigManager::Default));
      assertNoException();

      // user
      DynamicObject b;
      b[0] = 20;
      b[1] = 21;
      assert(cm.addConfig(b, ConfigManager::User));
      assertNoException();

      // custom
      cm.getConfig()[1] = 31;

      {
         // Changes from system configs
         DynamicObject expect;
         expect[0] = 20;
         expect[1] = 31;
         DynamicObject changes;
         cm.getChanges(changes);
         assertDynoCmp(changes, expect);
      }

      {
         // Changes from system+user configs
         DynamicObject expect;
         expect[0] = "__default__";
         expect[1] = 31;
         DynamicObject changes;
         cm.getChanges(changes, ConfigManager::All);
         assertDynoCmp(changes, expect);
      }
   }
   tr.passIfNoException();

   tr.test("default value");
   {
      ConfigManager cm;
      DynamicObject a;
      a = 1;
      assert(cm.addConfig(a));
      assertNoException();
      DynamicObject b;
      b = "__default__";
      assert(cm.addConfig(b));
      assertNoException();
      DynamicObject expect;
      expect = 1;
      assertDynoCmp(cm.getConfig(), expect);
   }
   tr.passIfNoException();

   tr.test("default values");
   {
      ConfigManager cm;
      DynamicObject a;
      a[0] = 10;
      a[1] = 11;
      a[2]["0"] = 120;
      a[2]["1"] = 121;
      assert(cm.addConfig(a));
      assertNoException();
      DynamicObject b;
      b[0] = "__default__";
      b[1] = 21;
      b[2]["0"] = "__default__";
      b[2]["1"] = 221;
      assert(cm.addConfig(b));
      assertNoException();
      DynamicObject expect;
      expect[0] = 10;
      expect[1] = 21;
      expect[2]["0"] = 120;
      expect[2]["1"] = 221;
      assertDynoCmp(cm.getConfig(), expect);
   }
   tr.passIfNoException();

   tr.test("schema check");
   {
      DynamicObject schema;
      DynamicObject config;
      assert(ConfigManager::isValidConfig(config, schema));
      schema->setType(Map);
      config->setType(Map);
      assert(ConfigManager::isValidConfig(config, schema));
      schema["s"] = "";
      schema["i"] = 0;
      config["s"] = "string";
      config["i"] = 1;
      assert(ConfigManager::isValidConfig(config, schema));
      schema["m"]["s"] = "";
      schema["m"]["s2"] = "";
      schema["a"][0] = 0;
      schema["a"][1] = 1;
      config["m"]["s"] = "s";
      config["m"]["s2"] = "s2";
      config["a"][0] = 0;
      config["a"][1] = 1;
   }
   tr.passIfNoException();

   tr.test("schema check bad");
   {
      DynamicObject schema;
      DynamicObject config;
      assert(ConfigManager::isValidConfig(config, schema));
      schema->setType(Map);
      config->setType(Array);
      assert(!ConfigManager::isValidConfig(config, schema));
      config->setType(Map);
      schema["s"] = "";
      schema["i"] = 0;
      config["s"] = 1;
      config["i"] = "string";
      assert(!ConfigManager::isValidConfig(config, schema));
   }
   tr.passIfNoException();

   tr.test("user preferences");
   {
      ConfigManager cm;

      // node
      // built in or loaded defaults
      DynamicObject nodec;
      nodec["node"]["host"] = "localhost";
      nodec["node"]["port"] = 19100;
      nodec["node"]["modulePath"] = "/usr/lib/bitmunk/modules";
      nodec["node"]["userModulePath"] = "~/.bitmunk/modules";
      assert(cm.addConfig(nodec));
      assertNoException();

      // user
      // loaded defaults
      DynamicObject userc;
      userc["node"]["port"] = 19100;
      userc["node"]["comment"] = "My precious...";
      assert(cm.addConfig(userc, ConfigManager::User));
      assertNoException();

      // user makes changes during runtime
      DynamicObject c = cm.getConfig();
      c["node"]["port"] = 19200;
      c["node"]["userModulePath"] = "~/.bitmunk/modules:~/.bitmunk/modules-dev";
      c["node"][ConfigManager::TMP]["not in changes"] = true;

      // get the changes from defaults to current config
      // serialize this to disk as needed
      DynamicObject changes;
      cm.getChanges(changes);

      // check it's correct
      DynamicObject expect;
      expect["node"]["port"] = 19200;
      expect["node"]["comment"] = "My precious...";
      expect["node"]["userModulePath"] = "~/.bitmunk/modules:~/.bitmunk/modules-dev";
      // NOTE: will not have TMP var
      assertDynoCmp(changes, expect);
   }
   tr.passIfNoException();

   tr.test("versioning");
   {
      ConfigManager cm;

      cm.getVersions()->clear();
      Config c;
      assert(cm.addConfig(c));
      assertNoException();

      cm.addVersion("1");
      assert(!cm.addConfig(c));
      assertException();
      Exception::clearLast();

      c[ConfigManager::VERSION] = "2";
      assert(!cm.addConfig(c));
      assertException();
      Exception::clearLast();

      c[ConfigManager::VERSION] = "1";
      assert(cm.addConfig(c));
      assertNoException();

      c[ConfigManager::VERSION] = "2";
      cm.addVersion("2");
      assert(cm.addConfig(c));
      assertNoException();
   }
   tr.passIfNoException();

   tr.test("empty array & map");
   {
      ConfigManager cm;
      DynamicObject a;
      a[0]->setType(Array);
      a[1]->setType(Map);
      assert(cm.addConfig(a));
      assertNoException();
      DynamicObject expect;
      expect[0]->setType(Array);
      expect[1]->setType(Map);
      assertDynoCmp(cm.getConfig(), expect);
   }
   tr.passIfNoException();

   tr.ungroup();
}

class DbConfigTester : public db::test::Tester
{
public:
   DbConfigTester()
   {
      setName("config");
   }

   /**
    * Run automatic unit tests.
    */
   virtual int runAutomaticTests(TestRunner& tr)
   {
      runConfigManagerTest(tr);
      return 0;
   }

   /**
    * Runs interactive unit tests.
    */
   virtual int runInteractiveTests(TestRunner& tr)
   {
      return 0;
   }
};

#ifndef DB_TEST_NO_MAIN
DB_TEST_MAIN(DbConfigTester)
#endif
<commit_msg>Clear expected exceptions.<commit_after>/*
 * Copyright (c) 2007-2008 Digital Bazaar, Inc.  All rights reserved.
 */
#include <iostream>
#include <sstream>

#include "db/rt/Exception.h"
#include "db/test/Test.h"
#include "db/test/Tester.h"
#include "db/test/TestRunner.h"
#include "db/config/ConfigManager.h"
#include "db/data/json/JsonWriter.h"

using namespace std;
using namespace db::rt;
using namespace db::test;
using namespace db::config;

void runConfigManagerTest(TestRunner& tr)
{
   tr.group("ConfigManager");

   tr.test("init");
   {
      DynamicObject expect;
      expect->setType(Map);
      ConfigManager cm;
      assertDynoCmp(cm.getConfig(), expect);
   }
   tr.passIfNoException();

   tr.test("init & clear");
   {
      DynamicObject expect;
      expect->setType(Map);
      ConfigManager cm;
      cm.clear();
      assertDynoCmp(cm.getConfig(), expect);
   }
   tr.passIfNoException();

   tr.test("1 config");
   {
      DynamicObject expect;
      expect->setType(Map);
      expect["a"] = 0;
      ConfigManager cm;
      DynamicObject a;
      a["a"] = 0;
      assert(cm.addConfig(a));
      assertNoException();
      assertDynoCmp(cm.getConfig(), expect);
   }
   tr.passIfNoException();

   tr.test("clear & 1 config");
   {
      DynamicObject expect;
      expect->setType(Map);
      expect["a"] = 0;
      ConfigManager cm;
      cm.clear();
      DynamicObject a;
      a["a"] = 0;
      assert(cm.addConfig(a));
      assertNoException();
      assertDynoCmp(cm.getConfig(), expect);
   }
   tr.passIfNoException();

   tr.test("config change");
   {
      ConfigManager cm;
      DynamicObject a;
      a["a"] = 0;
      assert(cm.addConfig(a));
      assertNoException();
      assertDynoCmp(cm.getConfig(), a);
      cm.getConfig()["a"] = 1;
      DynamicObject expect;
      expect["a"] = 1;
      assert(cm.getConfig() != a);
      assertDynoCmp(cm.getConfig(), expect);
   }
   tr.passIfNoException();

   tr.test("add");
   {
      DynamicObject expect;
      expect["a"] = 0;
      expect["b"] = 1;
      expect["c"] = 2;
      ConfigManager cm;
      DynamicObject a;
      a["a"] = 0;
      DynamicObject b;
      b["b"] = 1;
      DynamicObject c;
      c["c"] = 2;
      assert(cm.addConfig(a));
      assertNoException();
      assert(cm.addConfig(b));
      assertNoException();
      assert(cm.addConfig(c));
      assertNoException();
      assertDynoCmp(cm.getConfig(), expect);
   }
   tr.passIfNoException();

   tr.test("bad remove");
   {
      ConfigManager cm;
      assert(!cm.removeConfig(0));
      assertException();
      Exception::clearLast();
   }
   tr.passIfNoException();

   tr.test("remove");
   {
      DynamicObject expect;
      expect["a"] = 0;
      expect["b"] = 1;
      expect["c"] = 2;
      ConfigManager cm;
      DynamicObject a;
      a["a"] = 0;
      DynamicObject b;
      b["b"] = 1;
      DynamicObject c;
      c["c"] = 2;
      ConfigManager::ConfigId id;
      assert(cm.addConfig(a));
      assertNoException();
      assert(cm.addConfig(b, ConfigManager::Default, &id));
      assertNoException();
      assert(cm.addConfig(c));
      assertNoException();
      assertDynoCmp(cm.getConfig(), expect);
      DynamicObject expect2;
      expect2["a"] = 0;
      expect2["c"] = 2;
      assert(cm.removeConfig(id));
      assertDynoCmp(cm.getConfig(), expect2);
   }
   tr.passIfNoException();

   tr.test("update");
   {
      ConfigManager cm;
      DynamicObject expect;
      expect["a"] = 0;
      DynamicObject a;
      a["a"] = 0;
      assert(cm.addConfig(a));
      assertNoException();
      assertDynoCmp(cm.getConfig(), expect);
      DynamicObject expect2;
      expect2["a"] = 1;
      a["a"] = 1;
      assert(cm.getConfig() != expect2);
      cm.update();
      assertNoException();
      assertDynoCmp(cm.getConfig(), expect2);
   }
   tr.passIfNoException();

   tr.test("set");
   {
      ConfigManager cm;
      DynamicObject expect;
      expect["a"] = 0;
      DynamicObject a;
      a["a"] = 0;
      ConfigManager::ConfigId id;
      assert(cm.addConfig(a, ConfigManager::Default, &id));
      assertNoException();
      assertDynoCmp(cm.getConfig(), expect);
      DynamicObject expect2;
      expect2["b"] = 0;
      DynamicObject b;
      b["b"] = 0;
      cm.setConfig(id, b);
      assertDynoCmp(cm.getConfig(), expect2);
   }
   tr.passIfNoException();

   tr.test("get");
   {
      ConfigManager cm;
      DynamicObject expect;
      expect["a"] = 0;
      DynamicObject a;
      a["a"] = 0;
      ConfigManager::ConfigId id;
      assert(cm.addConfig(a, ConfigManager::Default, &id));
      assertNoException();
      assertDynoCmp(cm.getConfig(), expect);
      DynamicObject b;
      assert(cm.getConfig(id, b));
      assertDynoCmp(b, expect);
   }
   tr.passIfNoException();

   tr.test("map changes");
   {
      ConfigManager cm;
      DynamicObject a;
      a["a"] = 0;
      a["b"] = 0;
      assert(cm.addConfig(a));
      assertNoException();
      cm.getConfig()["a"] = 1;
      DynamicObject expect;
      expect["a"] = 1;
      DynamicObject changes;
      cm.getChanges(changes);
      assertDynoCmp(changes, expect);
   }
   tr.passIfNoException();

   tr.test("deep map changes");
   {
      ConfigManager cm;
      DynamicObject a;
      a["a"]["b"] = 0;
      a["a"]["c"] = 0;
      assert(cm.addConfig(a));
      assertNoException();
      cm.getConfig()["a"]["c"] = 1;
      cm.getConfig()["d"] = 0;
      DynamicObject expect;
      expect["a"]["c"] = 1;
      expect["d"] = 0;
      DynamicObject changes;
      cm.getChanges(changes);
      assertDynoCmp(changes, expect);
   }
   tr.passIfNoException();

   tr.test("array changes");
   {
      ConfigManager cm;
      DynamicObject a;
      a[0] = 10;
      a[1] = 11;
      a[2] = 12;
      assert(cm.addConfig(a));
      assertNoException();
      cm.getConfig()[1] = 21;
      DynamicObject expect;
      expect[0] = "__default__";
      expect[1] = 21;
      expect[2] = "__default__";
      DynamicObject changes;
      cm.getChanges(changes);
      assertDynoCmp(changes, expect);
   }
   tr.passIfNoException();

   tr.test("bigger array changes");
   {
      ConfigManager cm;
      DynamicObject a;
      a[0] = 10;
      a[1] = 11;
      assert(cm.addConfig(a));
      assertNoException();
      cm.getConfig()[2] = 22;
      DynamicObject expect;
      expect[0] = "__default__";
      expect[1] = "__default__";
      expect[2] = 22;
      DynamicObject changes;
      cm.getChanges(changes);
      assertDynoCmp(changes, expect);
   }
   tr.passIfNoException();

   tr.test("system vs user changes");
   {
      ConfigManager cm;

      // system
      DynamicObject a;
      a[0] = 10;
      a[1] = 11;
      assert(cm.addConfig(a, ConfigManager::Default));
      assertNoException();

      // user
      DynamicObject b;
      b[0] = 20;
      b[1] = 21;
      assert(cm.addConfig(b, ConfigManager::User));
      assertNoException();

      // custom
      cm.getConfig()[1] = 31;

      {
         // Changes from system configs
         DynamicObject expect;
         expect[0] = 20;
         expect[1] = 31;
         DynamicObject changes;
         cm.getChanges(changes);
         assertDynoCmp(changes, expect);
      }

      {
         // Changes from system+user configs
         DynamicObject expect;
         expect[0] = "__default__";
         expect[1] = 31;
         DynamicObject changes;
         cm.getChanges(changes, ConfigManager::All);
         assertDynoCmp(changes, expect);
      }
   }
   tr.passIfNoException();

   tr.test("default value");
   {
      ConfigManager cm;
      DynamicObject a;
      a = 1;
      assert(cm.addConfig(a));
      assertNoException();
      DynamicObject b;
      b = "__default__";
      assert(cm.addConfig(b));
      assertNoException();
      DynamicObject expect;
      expect = 1;
      assertDynoCmp(cm.getConfig(), expect);
   }
   tr.passIfNoException();

   tr.test("default values");
   {
      ConfigManager cm;
      DynamicObject a;
      a[0] = 10;
      a[1] = 11;
      a[2]["0"] = 120;
      a[2]["1"] = 121;
      assert(cm.addConfig(a));
      assertNoException();
      DynamicObject b;
      b[0] = "__default__";
      b[1] = 21;
      b[2]["0"] = "__default__";
      b[2]["1"] = 221;
      assert(cm.addConfig(b));
      assertNoException();
      DynamicObject expect;
      expect[0] = 10;
      expect[1] = 21;
      expect[2]["0"] = 120;
      expect[2]["1"] = 221;
      assertDynoCmp(cm.getConfig(), expect);
   }
   tr.passIfNoException();

   tr.test("schema check");
   {
      DynamicObject schema;
      DynamicObject config;
      assert(ConfigManager::isValidConfig(config, schema));
      schema->setType(Map);
      config->setType(Map);
      assert(ConfigManager::isValidConfig(config, schema));
      schema["s"] = "";
      schema["i"] = 0;
      config["s"] = "string";
      config["i"] = 1;
      assert(ConfigManager::isValidConfig(config, schema));
      schema["m"]["s"] = "";
      schema["m"]["s2"] = "";
      schema["a"][0] = 0;
      schema["a"][1] = 1;
      config["m"]["s"] = "s";
      config["m"]["s2"] = "s2";
      config["a"][0] = 0;
      config["a"][1] = 1;
   }
   tr.passIfNoException();

   tr.test("schema check bad");
   {
      DynamicObject schema;
      DynamicObject config;
      assert(ConfigManager::isValidConfig(config, schema));
      schema->setType(Map);
      config->setType(Array);
      assert(!ConfigManager::isValidConfig(config, schema));
      Exception::clearLast();
      config->setType(Map);
      schema["s"] = "";
      schema["i"] = 0;
      config["s"] = 1;
      config["i"] = "string";
      assert(!ConfigManager::isValidConfig(config, schema));
      Exception::clearLast();
   }
   tr.passIfNoException();

   tr.test("user preferences");
   {
      ConfigManager cm;

      // node
      // built in or loaded defaults
      DynamicObject nodec;
      nodec["node"]["host"] = "localhost";
      nodec["node"]["port"] = 19100;
      nodec["node"]["modulePath"] = "/usr/lib/bitmunk/modules";
      nodec["node"]["userModulePath"] = "~/.bitmunk/modules";
      assert(cm.addConfig(nodec));
      assertNoException();

      // user
      // loaded defaults
      DynamicObject userc;
      userc["node"]["port"] = 19100;
      userc["node"]["comment"] = "My precious...";
      assert(cm.addConfig(userc, ConfigManager::User));
      assertNoException();

      // user makes changes during runtime
      DynamicObject c = cm.getConfig();
      c["node"]["port"] = 19200;
      c["node"]["userModulePath"] = "~/.bitmunk/modules:~/.bitmunk/modules-dev";
      c["node"][ConfigManager::TMP]["not in changes"] = true;

      // get the changes from defaults to current config
      // serialize this to disk as needed
      DynamicObject changes;
      cm.getChanges(changes);

      // check it's correct
      DynamicObject expect;
      expect["node"]["port"] = 19200;
      expect["node"]["comment"] = "My precious...";
      expect["node"]["userModulePath"] = "~/.bitmunk/modules:~/.bitmunk/modules-dev";
      // NOTE: will not have TMP var
      assertDynoCmp(changes, expect);
   }
   tr.passIfNoException();

   tr.test("versioning");
   {
      ConfigManager cm;

      cm.getVersions()->clear();
      Config c;
      assert(cm.addConfig(c));
      assertNoException();

      cm.addVersion("1");
      assert(!cm.addConfig(c));
      assertException();
      Exception::clearLast();

      c[ConfigManager::VERSION] = "2";
      assert(!cm.addConfig(c));
      assertException();
      Exception::clearLast();

      c[ConfigManager::VERSION] = "1";
      assert(cm.addConfig(c));
      assertNoException();

      c[ConfigManager::VERSION] = "2";
      cm.addVersion("2");
      assert(cm.addConfig(c));
      assertNoException();
   }
   tr.passIfNoException();

   tr.test("empty array & map");
   {
      ConfigManager cm;
      DynamicObject a;
      a[0]->setType(Array);
      a[1]->setType(Map);
      assert(cm.addConfig(a));
      assertNoException();
      DynamicObject expect;
      expect[0]->setType(Array);
      expect[1]->setType(Map);
      assertDynoCmp(cm.getConfig(), expect);
   }
   tr.passIfNoException();

   tr.ungroup();
}

class DbConfigTester : public db::test::Tester
{
public:
   DbConfigTester()
   {
      setName("config");
   }

   /**
    * Run automatic unit tests.
    */
   virtual int runAutomaticTests(TestRunner& tr)
   {
      runConfigManagerTest(tr);
      return 0;
   }

   /**
    * Runs interactive unit tests.
    */
   virtual int runInteractiveTests(TestRunner& tr)
   {
      return 0;
   }
};

#ifndef DB_TEST_NO_MAIN
DB_TEST_MAIN(DbConfigTester)
#endif
<|endoftext|>