<commit_before>#include "dsa/crypto.h"
#include "dsa/responder.h"

#include <gtest/gtest.h>
#include <boost/filesystem/operations.hpp>
#include <boost/format.hpp>
#include <thread>
#include "../test_config.h"
#include "dslink.h"
#include "module/default/console_logger.h"
#include "module/logger.h"
#include "util/string.h"

#include "../async_test.h"
#include "dsa/stream.h"

#include "message/request/invoke_request_message.h"

using boost::format;

using namespace dsa;
using namespace std;

using DslinkTest = SetUpBase;
class MockNodeChild : public NodeModel {
 public:
  explicit MockNodeChild(LinkStrandRef strand, Var v)
      : NodeModel(std::move(strand)) {
    update_property("$is", Var(v));
  };
  bool save_child(const string_ &name) const override { return true; };
};

class MockNodeMain : public NodeModel {
 public:
  explicit MockNodeMain(LinkStrandRef strand) : NodeModel(std::move(strand)){};

  bool save_child(const string_ &name) const override {
    if (name == "Add_Child")
      return false;
    else
      return true;
  };

  void on_load_child(const string_ &name, VarMap &map) override {
    add_list_child(
        name, make_ref_<MockNodeChild>(this->_strand->get_ref(), Var(name)));
  };
};

TEST_F(DslinkTest, SaveMainNode) {
  shared_ptr<App> app = make_shared<App>();

  const char *argv[] = {"./testResp", "--broker",      "ds://127.0.0.1:4121",
                        "-l",         "info",          "--thread",
                        "4",          "--server-port", "4121"};
  int argc = 9;
  auto link = make_ref_<DsLink>(argc, argv, "mydslink", "1.0.0", app);
  // filter log for unit test
  static_cast<ConsoleLogger &>(Logger::_()).filter =
      Logger::FATAL_ | Logger::ERROR_ | Logger::WARN__;

  ref_<MockNodeMain> main_node =
      make_ref_<MockNodeMain>(link->strand->get_ref());
  main_node->add_list_child(
      "Add_Child",
      make_ref_<SimpleInvokeNode>(
          link->strand->get_ref(),
          [&](Var &&v, SimpleInvokeNode &node, OutgoingInvokeStream &stream,
              ref_<NodeState> &&parent) {

            auto *parent_model = parent->model_cast<NodeModel>();
            // add new child node
            parent_model->add_list_child(
                v.to_string(),
                make_ref_<MockNodeChild>(link->strand->get_ref(), v));

            stream.close();
          }));

  link->init_responder(main_node);
  bool invoked = false;
  bool invoked2 = false;
  ref_<IncomingListCache> list_cache;
  link->connect([&](const shared_ptr_<Connection> connection,
                    ref_<DsLinkRequester> link_req) {

    // invoke the Add_Child node to add new child
    auto request = make_ref_<InvokeRequestMessage>();
    request->set_target_path("Main/Add_Child");
    request->set_body(Var("Child_A").to_msgpack());
    link_req->invoke(
        [&](IncomingInvokeStream &, ref_<const InvokeResponseMessage> &&msg) {
          EXPECT_EQ(msg->get_status(), MessageStatus::CLOSED);
          invoked = true;
        },
        std::move(request));

    // invoke the Add_Child node to add second child
    auto request2 = make_ref_<InvokeRequestMessage>();
    request2->set_target_path("Main/Add_Child");
    request2->set_body(Var("Child_B").to_msgpack());
    link_req->invoke(
        [&](IncomingInvokeStream &, ref_<const InvokeResponseMessage> &&msg) {
          EXPECT_EQ(msg->get_status(), MessageStatus::CLOSED);
          invoked2 = true;
        },
        std::move(request2));

  });

  WAIT_EXPECT_TRUE(1000, [&]() -> bool { return invoked && invoked2; });

  SimpleStorage simple_storage(nullptr);

  std::string storage_key("vk123");

  std::unique_ptr<StorageBucket> storage_bucket =
      simple_storage.get_bucket("node");

  storage_bucket->remove_all();
  //save main node
  main_node->save(*storage_bucket, "Main", false, true);

  destroy_dslink_in_strand(link);
  main_node.reset();

  typedef std::vector<std::vector<string_>> ListResponses;
  auto link2 = make_ref_<DsLink>(argc, argv, "mydslink", "1.0.0", app);
  // filter log for unit test
  static_cast<ConsoleLogger &>(Logger::_()).filter =
      Logger::FATAL_ | Logger::ERROR_ | Logger::WARN__;

  ref_<MockNodeMain> main_node2 =
      make_ref_<MockNodeMain>(link2->strand->get_ref());
  main_node2->add_list_child(
      "Add_Child",
      make_ref_<SimpleInvokeNode>(
          link2->strand->get_ref(),
          [&](Var &&v, SimpleInvokeNode &node, OutgoingInvokeStream &stream,
              ref_<NodeState> &&parent) {

            auto *parent_model = parent->model_cast<NodeModel>();

            parent_model->add_list_child(
                v.to_string(),
                make_ref_<MockNodeChild>(link2->strand->get_ref(), v));

            stream.close();
          }));

  bool connected = false;
  bool flag1 = false;
  ListResponses root_list_responses;
  ref_<IncomingListCache> list_cache2;

  SimpleStorage simple_storage2(nullptr);

  std::unique_ptr<StorageBucket> storage_bucket2 =
      simple_storage2.get_bucket("node");

  int read_order = 0;
  auto read_all_callback = [&](std::string storage_key,
                               std::vector<uint8_t> vec,
                               BucketReadStatus read_status) {

    if (storage_key == "Main") {
      std::string str(vec.begin(), vec.end());

      auto v = Var::from_json(str);
      //load main node
      main_node2->load(v.get_map());
    }

    return;
  };

  storage_bucket2->read_all(read_all_callback, [&]() {
    EXPECT_EQ(read_order, 0);
    return;
  });

  link2->init_responder(std::move(main_node2));
  link2->connect([&](const shared_ptr_<Connection> connection,
                    ref_<DsLinkRequester> link_req) {
    connected = true;

    // list on Main node
    auto list_cache1 = link_req->list(
        "Main",
        [
              &,
              link_req = static_cast<ref_<DsLinkRequester>>(link_req->get_ref())
        ](IncomingListCache & cache, const std::vector<string_> &str) {
          root_list_responses.push_back(str);
          //verify structure of Main node
          EXPECT_TRUE(cache.get_map().size() != 0);
          {
            EXPECT_TRUE(root_list_responses.size() == 1);
            EXPECT_TRUE(root_list_responses[0].size() == 0);
            EXPECT_TRUE(cache.get_map().at("Child_A").is_map());
            EXPECT_EQ(
                cache.get_map().at("Child_A").get_map().at("$is").to_string(),
                "Child_A");
            EXPECT_TRUE(cache.get_map().at("Child_B").is_map());
            EXPECT_EQ(
                cache.get_map().at("Child_B").get_map().at("$is").to_string(),
                "Child_B");
          }
          flag1 = true;
        });
  });

  WAIT_EXPECT_TRUE(1000, [&]() -> bool { return connected && flag1; });

  destroy_dslink_in_strand(link2);
  storage_bucket2->remove_all();

  app->close();
  WAIT_EXPECT_TRUE(3000, [&]() -> bool { return app->is_stopped(); });

  if (!app->is_stopped()) {
    app->force_stop();
  }
  app->wait();
}
<commit_msg>fix shared bucket<commit_after>#include "dsa/crypto.h"
#include "dsa/responder.h"

#include <gtest/gtest.h>
#include <boost/filesystem/operations.hpp>
#include <boost/format.hpp>
#include <thread>
#include "../test_config.h"
#include "dslink.h"
#include "module/default/console_logger.h"
#include "module/logger.h"
#include "util/string.h"

#include "../async_test.h"
#include "dsa/stream.h"

#include "message/request/invoke_request_message.h"

using boost::format;

using namespace dsa;
using namespace std;

using DslinkTest = SetUpBase;
class MockNodeChild : public NodeModel {
 public:
  explicit MockNodeChild(LinkStrandRef strand, Var v)
      : NodeModel(std::move(strand)) {
    update_property("$is", Var(v));
  };
  bool save_child(const string_ &name) const override { return true; };
};

class MockNodeMain : public NodeModel {
 public:
  explicit MockNodeMain(LinkStrandRef strand) : NodeModel(std::move(strand)){};

  bool save_child(const string_ &name) const override {
    if (name == "Add_Child")
      return false;
    else
      return true;
  };

  void on_load_child(const string_ &name, VarMap &map) override {
    add_list_child(
        name, make_ref_<MockNodeChild>(this->_strand->get_ref(), Var(name)));
  };
};

TEST_F(DslinkTest, SaveMainNode) {
  shared_ptr<App> app = make_shared<App>();

  const char *argv[] = {"./testResp", "--broker",      "ds://127.0.0.1:4121",
                        "-l",         "info",          "--thread",
                        "4",          "--server-port", "4121"};
  int argc = 9;
  auto link = make_ref_<DsLink>(argc, argv, "mydslink", "1.0.0", app);
  // filter log for unit test
  static_cast<ConsoleLogger &>(Logger::_()).filter =
      Logger::FATAL_ | Logger::ERROR_ | Logger::WARN__;

  ref_<MockNodeMain> main_node =
      make_ref_<MockNodeMain>(link->strand->get_ref());
  main_node->add_list_child(
      "Add_Child",
      make_ref_<SimpleInvokeNode>(
          link->strand->get_ref(),
          [&](Var &&v, SimpleInvokeNode &node, OutgoingInvokeStream &stream,
              ref_<NodeState> &&parent) {

            auto *parent_model = parent->model_cast<NodeModel>();
            // add new child node
            parent_model->add_list_child(
                v.to_string(),
                make_ref_<MockNodeChild>(link->strand->get_ref(), v));

            stream.close();
          }));

  link->init_responder(main_node);
  bool invoked = false;
  bool invoked2 = false;
  ref_<IncomingListCache> list_cache;
  link->connect([&](const shared_ptr_<Connection> connection,
                    ref_<DsLinkRequester> link_req) {

    // invoke the Add_Child node to add new child
    auto request = make_ref_<InvokeRequestMessage>();
    request->set_target_path("Main/Add_Child");
    request->set_body(Var("Child_A").to_msgpack());
    link_req->invoke(
        [&](IncomingInvokeStream &, ref_<const InvokeResponseMessage> &&msg) {
          EXPECT_EQ(msg->get_status(), MessageStatus::CLOSED);
          invoked = true;
        },
        std::move(request));

    // invoke the Add_Child node to add second child
    auto request2 = make_ref_<InvokeRequestMessage>();
    request2->set_target_path("Main/Add_Child");
    request2->set_body(Var("Child_B").to_msgpack());
    link_req->invoke(
        [&](IncomingInvokeStream &, ref_<const InvokeResponseMessage> &&msg) {
          EXPECT_EQ(msg->get_status(), MessageStatus::CLOSED);
          invoked2 = true;
        },
        std::move(request2));

  });

  WAIT_EXPECT_TRUE(1000, [&]() -> bool { return invoked && invoked2; });

  SimpleStorage simple_storage(nullptr);

  std::string storage_key("vk123");

  shared_ptr_<StorageBucket> storage_bucket =
      simple_storage.get_shared_bucket("node");

  storage_bucket->remove_all();
  //save main node
  main_node->save(*storage_bucket, "Main", false, true);

  destroy_dslink_in_strand(link);
  main_node.reset();

  typedef std::vector<std::vector<string_>> ListResponses;
  auto link2 = make_ref_<DsLink>(argc, argv, "mydslink", "1.0.0", app);
  // filter log for unit test
  static_cast<ConsoleLogger &>(Logger::_()).filter =
      Logger::FATAL_ | Logger::ERROR_ | Logger::WARN__;

  ref_<MockNodeMain> main_node2 =
      make_ref_<MockNodeMain>(link2->strand->get_ref());
  main_node2->add_list_child(
      "Add_Child",
      make_ref_<SimpleInvokeNode>(
          link2->strand->get_ref(),
          [&](Var &&v, SimpleInvokeNode &node, OutgoingInvokeStream &stream,
              ref_<NodeState> &&parent) {

            auto *parent_model = parent->model_cast<NodeModel>();

            parent_model->add_list_child(
                v.to_string(),
                make_ref_<MockNodeChild>(link2->strand->get_ref(), v));

            stream.close();
          }));

  bool connected = false;
  bool flag1 = false;
  ListResponses root_list_responses;
  ref_<IncomingListCache> list_cache2;

  SimpleStorage simple_storage2(nullptr);

  shared_ptr_<StorageBucket> storage_bucket2 =
      simple_storage2.get_shared_bucket("node");

  int read_order = 0;
  auto read_all_callback = [&](std::string storage_key,
                               std::vector<uint8_t> vec,
                               BucketReadStatus read_status) {

    if (storage_key == "Main") {
      std::string str(vec.begin(), vec.end());

      auto v = Var::from_json(str);
      //load main node
      main_node2->load(v.get_map());
    }

    return;
  };

  storage_bucket2->read_all(read_all_callback, [&]() {
    EXPECT_EQ(read_order, 0);
    return;
  });

  link2->init_responder(std::move(main_node2));
  link2->connect([&](const shared_ptr_<Connection> connection,
                    ref_<DsLinkRequester> link_req) {
    connected = true;

    // list on Main node
    auto list_cache1 = link_req->list(
        "Main",
        [
              &,
              link_req = static_cast<ref_<DsLinkRequester>>(link_req->get_ref())
        ](IncomingListCache & cache, const std::vector<string_> &str) {
          root_list_responses.push_back(str);
          //verify structure of Main node
          EXPECT_TRUE(cache.get_map().size() != 0);
          {
            EXPECT_TRUE(root_list_responses.size() == 1);
            EXPECT_TRUE(root_list_responses[0].size() == 0);
            EXPECT_TRUE(cache.get_map().at("Child_A").is_map());
            EXPECT_EQ(
                cache.get_map().at("Child_A").get_map().at("$is").to_string(),
                "Child_A");
            EXPECT_TRUE(cache.get_map().at("Child_B").is_map());
            EXPECT_EQ(
                cache.get_map().at("Child_B").get_map().at("$is").to_string(),
                "Child_B");
          }
          flag1 = true;
        });
  });

  WAIT_EXPECT_TRUE(1000, [&]() -> bool { return connected && flag1; });

  destroy_dslink_in_strand(link2);
  storage_bucket2->remove_all();

  app->close();
  WAIT_EXPECT_TRUE(3000, [&]() -> bool { return app->is_stopped(); });

  if (!app->is_stopped()) {
    app->force_stop();
  }
  app->wait();
}
<|endoftext|>


<commit_before>/*****************************************************************************
 *
 * This file is part of Mapnik (c++ mapping toolkit)
 *
 * Copyright (C) 2015 Artem Pavlenko
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library 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
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 *
 *****************************************************************************/

#include "catch.hpp"

#include <mapnik/datasource.hpp>
#include <mapnik/datasource_cache.hpp>
#include <mapnik/mapped_memory_cache.hpp>
#include <mapnik/util/fs.hpp>
#include <cstdlib>
#include <fstream>
#pragma GCC diagnostic push
#include <mapnik/warning_ignore.hpp>
#include <boost/algorithm/string.hpp>
#pragma GCC diagnostic pop

namespace {

std::size_t count_shapefile_features(std::string const& filename)
{
#if defined(MAPNIK_MEMORY_MAPPED_FILE)
    mapnik::mapped_memory_cache::instance().clear();
#endif
    mapnik::parameters params;
    params["type"] = "shape";
    params["file"] = filename;
    auto ds = mapnik::datasource_cache::instance().create(params);
    REQUIRE(ds != nullptr);
    CHECK(ds->type() == mapnik::datasource::datasource_t::Vector);
    auto fields = ds->get_descriptor().get_descriptors();
    mapnik::query query(ds->envelope());
    for (auto const& field : fields)
    {
        query.add_property_name(field.get_name());
    }
    auto features = ds->features(query);
    REQUIRE(features != nullptr);

    std::size_t feature_count = 0;
    auto feature = features->next();
    while (feature)
    {
        ++feature_count;
        feature = features->next();
    }

    return feature_count;
}

int create_shapefile_index(std::string const& filename, bool index_parts, bool silent = true)
{
    std::string cmd;
    if (std::getenv("DYLD_LIBRARY_PATH") != nullptr)
    {
        cmd += std::string("DYLD_LIBRARY_PATH=") + std::getenv("DYLD_LIBRARY_PATH") + " ";
    }

    cmd += "shapeindex ";
    if (index_parts) cmd+= "--index-parts ";
    cmd += filename;
    if (silent)
    {
#ifndef _WINDOWS
        cmd += " 2>/dev/null";
#else
        cmd += " 2> nul";
#endif
    }
    return std::system(cmd.c_str());
}

}

TEST_CASE("invalid shapeindex")
{
    std::string shape_plugin("./plugins/input/shape.input");
    if (mapnik::util::exists(shape_plugin))
    {
        SECTION("Invalid index")
        {
            std::string path = "test/data/shp/boundaries.shp";
            std::string index_path = path.substr(0, path.rfind(".")) + ".index";
            // remove *.index if present
            if (mapnik::util::exists(index_path))
            {
                mapnik::util::remove(index_path);
            }
            // count features

            std::size_t feature_count = count_shapefile_features(path);

            // create invalid index
            std::ofstream index(index_path.c_str(), std::ios::binary);
            std::string buf("mapnik-invalid-index.................");
            index.write(buf.c_str(), buf.size());
            index.close();

            // count features
            std::size_t feature_count_indexed = count_shapefile_features(path);
            // ensure number of features are the same
            REQUIRE(feature_count == feature_count_indexed);
            // remove *.index if present
            if (mapnik::util::exists(index_path))
            {
                mapnik::util::remove(index_path);
            }
        }
    }
}

TEST_CASE("shapeindex")
{
    std::string shape_plugin("./plugins/input/shape.input");
    if (mapnik::util::exists(shape_plugin))
    {
        SECTION("Index")
        {
            for (auto const& path : mapnik::util::list_directory("test/data/shp/"))
            {
                if (boost::iends_with(path,".shp"))
                {
                    for (bool index_parts : {false, true} )
                    {
                        CAPTURE(path);
                        CAPTURE(index_parts);

                        std::string index_path = path.substr(0, path.rfind(".")) + ".index";
                        // remove *.index if present
                        if (mapnik::util::exists(index_path))
                        {
                            mapnik::util::remove(index_path);
                        }
                        // count features
                        std::size_t feature_count = count_shapefile_features(path);
                        // create *.index
                        REQUIRE(create_shapefile_index(path, index_parts) == 0);
                        if (feature_count == 0)
                        {
                            REQUIRE(!mapnik::util::exists(index_path)); // index won't be created if there's no features
                        }
                        // count features
                        std::size_t feature_count_indexed = count_shapefile_features(path);
                        // ensure number of features are the same
                        REQUIRE(feature_count == feature_count_indexed);
                        // remove *.index if present
                        if (mapnik::util::exists(index_path))
                        {
                            mapnik::util::remove(index_path);
                        }
                    }
                }
            }
        }
    }
}
<commit_msg>test bogus *.index files are handled correctly (ref #3300)  + indirectly tests #3306 via requiring `mapped_memory_cache::instance().clear()`<commit_after>/*****************************************************************************
 *
 * This file is part of Mapnik (c++ mapping toolkit)
 *
 * Copyright (C) 2015 Artem Pavlenko
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library 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
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 *
 *****************************************************************************/

#include "catch.hpp"

#include <mapnik/datasource.hpp>
#include <mapnik/datasource_cache.hpp>
#include <mapnik/mapped_memory_cache.hpp>
#include <mapnik/util/fs.hpp>
#include <cstdlib>
#include <fstream>
#pragma GCC diagnostic push
#include <mapnik/warning_ignore.hpp>
#include <boost/algorithm/string.hpp>
#pragma GCC diagnostic pop

namespace {

std::size_t count_shapefile_features(std::string const& filename)
{
#if defined(MAPNIK_MEMORY_MAPPED_FILE)
    mapnik::mapped_memory_cache::instance().clear();
#endif
    mapnik::parameters params;
    params["type"] = "shape";
    params["file"] = filename;
    auto ds = mapnik::datasource_cache::instance().create(params);
    REQUIRE(ds != nullptr);
    CHECK(ds->type() == mapnik::datasource::datasource_t::Vector);
    auto fields = ds->get_descriptor().get_descriptors();
    mapnik::query query(ds->envelope());
    for (auto const& field : fields)
    {
        query.add_property_name(field.get_name());
    }
    auto features = ds->features(query);
    REQUIRE(features != nullptr);

    std::size_t feature_count = 0;
    auto feature = features->next();
    while (feature)
    {
        ++feature_count;
        feature = features->next();
    }

    return feature_count;
}

int create_shapefile_index(std::string const& filename, bool index_parts, bool silent = true)
{
    std::string cmd;
    if (std::getenv("DYLD_LIBRARY_PATH") != nullptr)
    {
        cmd += std::string("DYLD_LIBRARY_PATH=") + std::getenv("DYLD_LIBRARY_PATH") + " ";
    }

    cmd += "shapeindex ";
    if (index_parts) cmd+= "--index-parts ";
    cmd += filename;
    if (silent)
    {
#ifndef _WINDOWS
        cmd += " 2>/dev/null";
#else
        cmd += " 2> nul";
#endif
    }
    return std::system(cmd.c_str());
}

}

TEST_CASE("invalid shapeindex")
{
    std::string shape_plugin("./plugins/input/shape.input");
    if (mapnik::util::exists(shape_plugin))
    {
        SECTION("Invalid index")
        {
            for (auto val : {std::make_tuple(true, std::string("mapnik-invalid-index.................")), // invalid header
                           std::make_tuple(false, std::string("mapnik-index................."))})       // valid header + invalid index
            {
                std::string path = "test/data/shp/boundaries.shp";
                std::string index_path = path.substr(0, path.rfind(".")) + ".index";
                // remove *.index if present
                if (mapnik::util::exists(index_path))
                {
                    mapnik::util::remove(index_path);
                }
                // count features

                std::size_t feature_count = count_shapefile_features(path);

                // create index
                std::ofstream index(index_path.c_str(), std::ios::binary);
                index.write(std::get<1>(val).c_str(), std::get<1>(val).size());
                index.close();

                // count features
                std::size_t feature_count_indexed = count_shapefile_features(path);
                if (std::get<0>(val)) // fallback to un-indexed access
                {
                    // ensure number of features are the same
                    CHECK(feature_count == feature_count_indexed);
                }
                else // the header is valid but index file itself is not - expect datasource to fail and return 0 features.
                {
                    CHECK(feature_count_indexed == 0);
                }
                // remove *.index if present
                if (mapnik::util::exists(index_path))
                {
                    mapnik::util::remove(index_path);
                }
            }
        }
    }
}

TEST_CASE("shapeindex")
{
    std::string shape_plugin("./plugins/input/shape.input");
    if (mapnik::util::exists(shape_plugin))
    {
        SECTION("Index")
        {
            for (auto const& path : mapnik::util::list_directory("test/data/shp/"))
            {
                if (boost::iends_with(path,".shp"))
                {
                    for (bool index_parts : {false, true} )
                    {
                        CAPTURE(path);
                        CAPTURE(index_parts);

                        std::string index_path = path.substr(0, path.rfind(".")) + ".index";
                        // remove *.index if present
                        if (mapnik::util::exists(index_path))
                        {
                            mapnik::util::remove(index_path);
                        }
                        // count features
                        std::size_t feature_count = count_shapefile_features(path);
                        // create *.index
                        REQUIRE(create_shapefile_index(path, index_parts) == 0);
                        if (feature_count == 0)
                        {
                            REQUIRE(!mapnik::util::exists(index_path)); // index won't be created if there's no features
                        }
                        // count features
                        std::size_t feature_count_indexed = count_shapefile_features(path);
                        // ensure number of features are the same
                        REQUIRE(feature_count == feature_count_indexed);
                        // remove *.index if present
                        if (mapnik::util::exists(index_path))
                        {
                            mapnik::util::remove(index_path);
                        }
                    }
                }
            }
        }
    }
}
<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  $RCSfile: operators_new_delete.cxx,v $
 *
 *  $Revision: 1.2 $
 *
 *  last change: $Author: hr $ $Date: 2003-03-26 16:45:33 $
 *
 *  The Contents of this file are made available subject to the terms of
 *  either of the following licenses
 *
 *         - GNU Lesser General Public License Version 2.1
 *         - Sun Industry Standards Source License Version 1.1
 *
 *  Sun Microsystems Inc., October, 2000
 *
 *  GNU Lesser General Public License Version 2.1
 *  =============================================
 *  Copyright 2000 by Sun Microsystems, Inc.
 *  901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License version 2.1, as published by the Free Software Foundation.
 *
 *  This library 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
 *  Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this library; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *  MA  02111-1307  USA
 *
 *
 *  Sun Industry Standards Source License Version 1.1
 *  =================================================
 *  The contents of this file are subject to the Sun Industry Standards
 *  Source License Version 1.1 (the "License"); You may not use this file
 *  except in compliance with the License. You may obtain a copy of the
 *  License at http://www.openoffice.org/license.html.
 *
 *  Software provided under this License is provided on an "AS IS" basis,
 *  WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
 *  WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
 *  MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
 *  See the License for the specific provisions governing your rights and
 *  obligations concerning the Software.
 *
 *  The Initial Developer of the Original Code is: Sun Microsystems, Inc.
 *
 *  Copyright: 2000 by Sun Microsystems, Inc.
 *
 *  All Rights Reserved.
 *
 *  Contributor(s): _______________________________________
 *
 *
 ************************************************************************/

#ifdef WNT /* avoid 'std::bad_alloc' unresolved externals */
#define _CRTIMP
#define _NTSDK
#endif /* WNT */

#ifndef INCLUDED_ALGORITHM
#include <algorithm>
#define INCLUDED_ALGORITHM
#endif

#ifndef INCLUDED_NEW
#include <new>
#define INCLUDED_NEW
#endif

#ifndef INCLUDED_STRING_H
#include <string.h>
#define INCLUDED_STRING_H
#endif

#ifndef _OSL_DIAGNOSE_H_
#include <osl/diagnose.h>
#endif

#ifndef _RTL_ALLOC_H_
#include <rtl/alloc.h>
#endif

using std::nothrow_t;

// =======================================================================
// AllocatorTraits
// =======================================================================

namespace
{

struct AllocatorTraits
{
    typedef char const signature_type[8];
    const signature_type & m_signature;

    explicit AllocatorTraits (signature_type const & s) SAL_THROW(())
        : m_signature (s)
    {}

    std::size_t size (std::size_t n) const SAL_THROW(())
    {
        n = std::max(n, std::size_t(1));
#if defined(DEBUG) || defined(_DEBUG)
        n += sizeof(signature_type);
#endif  /* DEBUG  */
        return n;
    }

    void* init (void * p) const SAL_THROW(())
    {
#if defined(DEBUG) || defined(_DEBUG)
        memcpy (p, m_signature, sizeof(signature_type));
        p = static_cast<char*>(p) + sizeof(signature_type);
#endif  /* DEBUG */
        return p;
    }

    void* fini (void * p) const SAL_THROW(())
    {
#if defined(DEBUG) || defined(_DEBUG)
        p = static_cast<char*>(p) - sizeof(signature_type);
        if (memcmp (p, m_signature, sizeof(signature_type)) != 0)
        {
            OSL_ENSURE(0, "operator delete mismatch");
        }
#endif  /* DEBUG */
        return p;
    }
};

// =======================================================================

struct VectorTraits : public AllocatorTraits
{
    static const signature_type g_signature;

    VectorTraits() SAL_THROW(())
        : AllocatorTraits (g_signature)
    {}
};

struct ScalarTraits : public AllocatorTraits
{
    static const signature_type g_signature;

    ScalarTraits() SAL_THROW(())
        : AllocatorTraits (g_signature)
    {}
};

const AllocatorTraits::signature_type VectorTraits::g_signature = "new[]()";
const AllocatorTraits::signature_type ScalarTraits::g_signature = "new()  ";

} // anonymous namespace

// =======================================================================
// Allocator
// =======================================================================

static void default_handler (void)
{
    // Multithreading race in 'std::set_new_handler()' call sequence below.
    throw std::bad_alloc();
}

// =======================================================================

static void* allocate (
    std::size_t n, AllocatorTraits const & rTraits)
    SAL_THROW((std::bad_alloc))
{
    n = rTraits.size (n);
    for (;;)
    {
        void * p = rtl_allocateMemory (sal_uInt32(n));
        if (p != 0)
            return rTraits.init (p);

        std::new_handler d = default_handler, f = std::set_new_handler (d);
        if (f != d)
            std::set_new_handler (f);

        if (f == 0)
            throw std::bad_alloc();
        (*f)();
    }
}

// =======================================================================

static void* allocate (
    std::size_t n, AllocatorTraits const & rTraits, std::nothrow_t const &)
    SAL_THROW(())
{
    try
    {
        return allocate (n, rTraits);
    }
    catch (std::bad_alloc const &)
    {
        return (0);
    }
}

// =======================================================================

static void deallocate (void * p, AllocatorTraits const & rTraits)
    SAL_THROW(())
{
    if (p)
    {
        rtl_freeMemory (rTraits.fini(p));
    }
}

// =======================================================================
// T * p = new T; delete p;
// =======================================================================

void* SAL_CALL operator new (std::size_t n) throw (std::bad_alloc)
{
    return allocate (n, ScalarTraits());
}

// =======================================================================

void SAL_CALL operator delete (void * p) throw ()
{
    deallocate (p, ScalarTraits());
}

// =======================================================================
// T * p = new(nothrow) T; delete(nothrow) p;
// =======================================================================

void* SAL_CALL operator new (std::size_t n, std::nothrow_t const &) throw ()
{
    return allocate (n, ScalarTraits(), nothrow_t());
}

// =======================================================================

void SAL_CALL operator delete (void * p, std::nothrow_t const &) throw ()
{
    deallocate (p, ScalarTraits());
}

// =======================================================================
// T * p = new T[n]; delete[] p;
// =======================================================================

void* SAL_CALL operator new[] (std::size_t n) throw (std::bad_alloc)
{
    return allocate (n, VectorTraits());
}

// =======================================================================

void SAL_CALL operator delete[] (void * p) throw ()
{
    deallocate (p, VectorTraits());
}

// =======================================================================
// T * p = new(nothrow) T[n]; delete(nothrow)[] p;
// =======================================================================

void* SAL_CALL operator new[] (std::size_t n, std::nothrow_t const &) throw ()
{
    return allocate (n, VectorTraits(), nothrow_t());
}

// =======================================================================

void SAL_CALL operator delete[] (void * p, std::nothrow_t const &) throw ()
{
    deallocate (p, VectorTraits());
}

// =======================================================================
<commit_msg>INTEGRATION: CWS dbgmacros1 (1.1.4.1.42); FILE MERGED 2003/04/09 12:08:11 kso 1.1.4.1.42.1: #108413# - debug macro unification.<commit_after>/*************************************************************************
 *
 *  $RCSfile: operators_new_delete.cxx,v $
 *
 *  $Revision: 1.3 $
 *
 *  last change: $Author: vg $ $Date: 2003-04-15 17:40:45 $
 *
 *  The Contents of this file are made available subject to the terms of
 *  either of the following licenses
 *
 *         - GNU Lesser General Public License Version 2.1
 *         - Sun Industry Standards Source License Version 1.1
 *
 *  Sun Microsystems Inc., October, 2000
 *
 *  GNU Lesser General Public License Version 2.1
 *  =============================================
 *  Copyright 2000 by Sun Microsystems, Inc.
 *  901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License version 2.1, as published by the Free Software Foundation.
 *
 *  This library 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
 *  Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this library; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *  MA  02111-1307  USA
 *
 *
 *  Sun Industry Standards Source License Version 1.1
 *  =================================================
 *  The contents of this file are subject to the Sun Industry Standards
 *  Source License Version 1.1 (the "License"); You may not use this file
 *  except in compliance with the License. You may obtain a copy of the
 *  License at http://www.openoffice.org/license.html.
 *
 *  Software provided under this License is provided on an "AS IS" basis,
 *  WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
 *  WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
 *  MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
 *  See the License for the specific provisions governing your rights and
 *  obligations concerning the Software.
 *
 *  The Initial Developer of the Original Code is: Sun Microsystems, Inc.
 *
 *  Copyright: 2000 by Sun Microsystems, Inc.
 *
 *  All Rights Reserved.
 *
 *  Contributor(s): _______________________________________
 *
 *
 ************************************************************************/

#ifdef WNT /* avoid 'std::bad_alloc' unresolved externals */
#define _CRTIMP
#define _NTSDK
#endif /* WNT */

#ifndef INCLUDED_ALGORITHM
#include <algorithm>
#define INCLUDED_ALGORITHM
#endif

#ifndef INCLUDED_NEW
#include <new>
#define INCLUDED_NEW
#endif

#ifndef INCLUDED_STRING_H
#include <string.h>
#define INCLUDED_STRING_H
#endif

#ifndef _OSL_DIAGNOSE_H_
#include <osl/diagnose.h>
#endif

#ifndef _RTL_ALLOC_H_
#include <rtl/alloc.h>
#endif

using std::nothrow_t;

// =======================================================================
// AllocatorTraits
// =======================================================================

namespace
{

struct AllocatorTraits
{
    typedef char const signature_type[8];
    const signature_type & m_signature;

    explicit AllocatorTraits (signature_type const & s) SAL_THROW(())
        : m_signature (s)
    {}

    std::size_t size (std::size_t n) const SAL_THROW(())
    {
        n = std::max(n, std::size_t(1));
#if OSL_DEBUG_LEVEL > 0
        n += sizeof(signature_type);
#endif  /* OSL_DEBUG_LEVEL  */
        return n;
    }

    void* init (void * p) const SAL_THROW(())
    {
#if OSL_DEBUG_LEVEL > 0
        memcpy (p, m_signature, sizeof(signature_type));
        p = static_cast<char*>(p) + sizeof(signature_type);
#endif  /* OSL_DEBUG_LEVEL */
        return p;
    }

    void* fini (void * p) const SAL_THROW(())
    {
#if OSL_DEBUG_LEVEL > 0
        p = static_cast<char*>(p) - sizeof(signature_type);
        if (memcmp (p, m_signature, sizeof(signature_type)) != 0)
        {
            OSL_ENSURE(0, "operator delete mismatch");
        }
#endif  /* OSL_DEBUG_LEVEL */
        return p;
    }
};

// =======================================================================

struct VectorTraits : public AllocatorTraits
{
    static const signature_type g_signature;

    VectorTraits() SAL_THROW(())
        : AllocatorTraits (g_signature)
    {}
};

struct ScalarTraits : public AllocatorTraits
{
    static const signature_type g_signature;

    ScalarTraits() SAL_THROW(())
        : AllocatorTraits (g_signature)
    {}
};

const AllocatorTraits::signature_type VectorTraits::g_signature = "new[]()";
const AllocatorTraits::signature_type ScalarTraits::g_signature = "new()  ";

} // anonymous namespace

// =======================================================================
// Allocator
// =======================================================================

static void default_handler (void)
{
    // Multithreading race in 'std::set_new_handler()' call sequence below.
    throw std::bad_alloc();
}

// =======================================================================

static void* allocate (
    std::size_t n, AllocatorTraits const & rTraits)
    SAL_THROW((std::bad_alloc))
{
    n = rTraits.size (n);
    for (;;)
    {
        void * p = rtl_allocateMemory (sal_uInt32(n));
        if (p != 0)
            return rTraits.init (p);

        std::new_handler d = default_handler, f = std::set_new_handler (d);
        if (f != d)
            std::set_new_handler (f);

        if (f == 0)
            throw std::bad_alloc();
        (*f)();
    }
}

// =======================================================================

static void* allocate (
    std::size_t n, AllocatorTraits const & rTraits, std::nothrow_t const &)
    SAL_THROW(())
{
    try
    {
        return allocate (n, rTraits);
    }
    catch (std::bad_alloc const &)
    {
        return (0);
    }
}

// =======================================================================

static void deallocate (void * p, AllocatorTraits const & rTraits)
    SAL_THROW(())
{
    if (p)
    {
        rtl_freeMemory (rTraits.fini(p));
    }
}

// =======================================================================
// T * p = new T; delete p;
// =======================================================================

void* SAL_CALL operator new (std::size_t n) throw (std::bad_alloc)
{
    return allocate (n, ScalarTraits());
}

// =======================================================================

void SAL_CALL operator delete (void * p) throw ()
{
    deallocate (p, ScalarTraits());
}

// =======================================================================
// T * p = new(nothrow) T; delete(nothrow) p;
// =======================================================================

void* SAL_CALL operator new (std::size_t n, std::nothrow_t const &) throw ()
{
    return allocate (n, ScalarTraits(), nothrow_t());
}

// =======================================================================

void SAL_CALL operator delete (void * p, std::nothrow_t const &) throw ()
{
    deallocate (p, ScalarTraits());
}

// =======================================================================
// T * p = new T[n]; delete[] p;
// =======================================================================

void* SAL_CALL operator new[] (std::size_t n) throw (std::bad_alloc)
{
    return allocate (n, VectorTraits());
}

// =======================================================================

void SAL_CALL operator delete[] (void * p) throw ()
{
    deallocate (p, VectorTraits());
}

// =======================================================================
// T * p = new(nothrow) T[n]; delete(nothrow)[] p;
// =======================================================================

void* SAL_CALL operator new[] (std::size_t n, std::nothrow_t const &) throw ()
{
    return allocate (n, VectorTraits(), nothrow_t());
}

// =======================================================================

void SAL_CALL operator delete[] (void * p, std::nothrow_t const &) throw ()
{
    deallocate (p, VectorTraits());
}

// =======================================================================
<|endoftext|>


<commit_before>/*
 * Copyright 2010 Apple Inc. All rights reserved.
 * Copyright (C) 2012 Samsung Electronics. 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.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#include "config.h"
#include "modules/device_orientation/NewDeviceOrientationController.h"

#include "core/dom/Document.h"
#include "modules/device_orientation/DeviceOrientationData.h"
#include "modules/device_orientation/DeviceOrientationDispatcher.h"
#include "modules/device_orientation/DeviceOrientationEvent.h"

namespace WebCore {

NewDeviceOrientationController::NewDeviceOrientationController(Document* document)
    : DeviceSensorEventController(document)
{
}

NewDeviceOrientationController::~NewDeviceOrientationController()
{
}

void NewDeviceOrientationController::didChangeDeviceOrientation(DeviceOrientationData* deviceOrientationData)
{
    dispatchDeviceEvent(DeviceOrientationEvent::create(eventNames().deviceorientationEvent, deviceOrientationData));
}

const char* NewDeviceOrientationController::supplementName()
{
    return "NewDeviceOrientationController";
}

NewDeviceOrientationController* NewDeviceOrientationController::from(Document* document)
{
    NewDeviceOrientationController* controller = static_cast<NewDeviceOrientationController*>(Supplement<ScriptExecutionContext>::from(document, supplementName()));
    if (!controller) {
        controller = new NewDeviceOrientationController(document);
        Supplement<ScriptExecutionContext>::provideTo(document, supplementName(), adoptPtr(controller));
    }
    return controller;
}

bool NewDeviceOrientationController::hasLastData()
{
    return DeviceOrientationDispatcher::instance().latestDeviceOrientationData();
}

PassRefPtr<Event> NewDeviceOrientationController::getLastEvent()
{
    return DeviceOrientationEvent::create(eventNames().deviceorientationEvent,
        DeviceOrientationDispatcher::instance().latestDeviceOrientationData());
}

void NewDeviceOrientationController::registerWithDispatcher()
{
    DeviceOrientationDispatcher::instance().addDeviceOrientationController(this);
}

void NewDeviceOrientationController::unregisterWithDispatcher()
{
    DeviceOrientationDispatcher::instance().removeDeviceOrientationController(this);
}

bool NewDeviceOrientationController::isNullEvent(Event* event)
{
    ASSERT(event->type() == eventNames().devicemotionEvent);
    DeviceOrientationEvent* orientationEvent = static_cast<DeviceOrientationEvent*>(event);
    return !orientationEvent->orientation()->canProvideEventData();
}

} // namespace WebCore
<commit_msg>Fix buggy ASSERT in NewDeviceOrientationController.<commit_after>/*
 * Copyright 2010 Apple Inc. All rights reserved.
 * Copyright (C) 2012 Samsung Electronics. 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.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#include "config.h"
#include "modules/device_orientation/NewDeviceOrientationController.h"

#include "core/dom/Document.h"
#include "modules/device_orientation/DeviceOrientationData.h"
#include "modules/device_orientation/DeviceOrientationDispatcher.h"
#include "modules/device_orientation/DeviceOrientationEvent.h"

namespace WebCore {

NewDeviceOrientationController::NewDeviceOrientationController(Document* document)
    : DeviceSensorEventController(document)
{
}

NewDeviceOrientationController::~NewDeviceOrientationController()
{
}

void NewDeviceOrientationController::didChangeDeviceOrientation(DeviceOrientationData* deviceOrientationData)
{
    dispatchDeviceEvent(DeviceOrientationEvent::create(eventNames().deviceorientationEvent, deviceOrientationData));
}

const char* NewDeviceOrientationController::supplementName()
{
    return "NewDeviceOrientationController";
}

NewDeviceOrientationController* NewDeviceOrientationController::from(Document* document)
{
    NewDeviceOrientationController* controller = static_cast<NewDeviceOrientationController*>(Supplement<ScriptExecutionContext>::from(document, supplementName()));
    if (!controller) {
        controller = new NewDeviceOrientationController(document);
        Supplement<ScriptExecutionContext>::provideTo(document, supplementName(), adoptPtr(controller));
    }
    return controller;
}

bool NewDeviceOrientationController::hasLastData()
{
    return DeviceOrientationDispatcher::instance().latestDeviceOrientationData();
}

PassRefPtr<Event> NewDeviceOrientationController::getLastEvent()
{
    return DeviceOrientationEvent::create(eventNames().deviceorientationEvent,
        DeviceOrientationDispatcher::instance().latestDeviceOrientationData());
}

void NewDeviceOrientationController::registerWithDispatcher()
{
    DeviceOrientationDispatcher::instance().addDeviceOrientationController(this);
}

void NewDeviceOrientationController::unregisterWithDispatcher()
{
    DeviceOrientationDispatcher::instance().removeDeviceOrientationController(this);
}

bool NewDeviceOrientationController::isNullEvent(Event* event)
{
    ASSERT(event->type() == eventNames().deviceorientationEvent);
    DeviceOrientationEvent* orientationEvent = static_cast<DeviceOrientationEvent*>(event);
    return !orientationEvent->orientation()->canProvideEventData();
}

} // namespace WebCore
<|endoftext|>


<commit_before>/********************************************************************
  Motor.cpp - A Library for Controlling the Motors of the MRK-1
  An Introduction to Robot Programming
  Author - Eric Ryan Harrison <me@ericharrison.info>
  http://github.com/SumoRobotLeague/MRK-1/

  Improved motor control library with an attack() method that will
  instantly charge forward at full speed on both motors.
********************************************************************/

#include "Arduino.h"
#include "Motor.h"

// Define our minimum and maximum speeds for error checking.
#define maxSpeed 255
#define minSpeed -255

// This is our class constructor. When this method is called
// the class will create an object of this instance. We don't
// need our motor constructor to do anything, so we will leave
// it empty.
Motor::Motor() {
	// Intentionally do nothing
}

void Motor::setupRight(int rightSpeed_pin, int rightDirection_pin) {
	// Store the pin in a private variable for later use
	_rightMotorSpeedPin     = rightSpeed_pin;
	_rightMotorDirectionPin = rightDirection_pin;

	// Set up pins for output
	pinMode(_rightMotorSpeedPin,     OUTPUT);
	pinMode(_rightMotorDirectionPin, OUTPUT);
}

void Motor::setupLeft(int leftSpeed_pin, int leftDirection_pin) {
	// Store the pin in a private variable for later use
	_leftMotorSpeedPin     = leftSpeed_pin;
	_leftMotorDirectionPin = leftDirection_pin;

	// Set up pins for output
	pinMode(_leftMotorSpeedPin,     OUTPUT);
	pinMode(_leftMotorDirectionPin, OUTPUT);
}

void Motor::right(int speed) {
	// Simple check to make sure our speed does not exceed
	// the defined speed limits.
	if ( speed > maxSpeed ) {
		speed = maxSpeed;
	} else if ( speed < minSpeed ) {
		speed = minSpeed;
	}

	if ( speed < 0 ) {
		digitalWrite(_rightMotorDirectionPin, HIGH);
		analogWrite(_rightMotorSpeedPin, abs(speed));
	} else {
		digitalWrite(_rightMotorDirectionPin, LOW);
		analogWrite(_rightMotorSpeedPin, speed);
	}
}

void Motor::left(int speed) {
	if ( speed > maxSpeed ) {
		speed = maxSpeed;
	} else if ( speed < minSpeed ) {
		speed = minSpeed;
	}

	if ( speed < 0 ) {
		digitalWrite(_leftMotorDirectionPin, LOW);
		analogWrite(_leftMotorSpeedPin, speed);
	} else {
		digitalWrite(_leftMotorDirectionPin, HIGH);
		analogWrite(_leftMotorSpeedPin, abs(speed));
	}
}

// Our attack() method is a very simple function that will
// tell both motors to charge forward at full speed.
void Motor::attack() {
	right(maxSpeed);
	left(maxSpeed);
}

// Our abort() method is a very simple function that will
// tell both motors to reverse at full speed.
void Motor::abort() {
	right(minSpeed);
	left(minSpeed);
}
<commit_msg>Fixed the misplaced abs()<commit_after>/********************************************************************
  Motor.cpp - A Library for Controlling the Motors of the MRK-1
  An Introduction to Robot Programming
  Author - Eric Ryan Harrison <me@ericharrison.info>
  http://github.com/SumoRobotLeague/MRK-1/

  Improved motor control library with an attack() method that will
  instantly charge forward at full speed on both motors.
********************************************************************/

#include "Arduino.h"
#include "Motor.h"

// Define our minimum and maximum speeds for error checking.
#define maxSpeed 255
#define minSpeed -255

// This is our class constructor. When this method is called
// the class will create an object of this instance. We don't
// need our motor constructor to do anything, so we will leave
// it empty.
Motor::Motor() {
	// Intentionally do nothing
}

void Motor::setupRight(int rightSpeed_pin, int rightDirection_pin) {
	// Store the pin in a private variable for later use
	_rightMotorSpeedPin     = rightSpeed_pin;
	_rightMotorDirectionPin = rightDirection_pin;

	// Set up pins for output
	pinMode(_rightMotorSpeedPin,     OUTPUT);
	pinMode(_rightMotorDirectionPin, OUTPUT);
}

void Motor::setupLeft(int leftSpeed_pin, int leftDirection_pin) {
	// Store the pin in a private variable for later use
	_leftMotorSpeedPin     = leftSpeed_pin;
	_leftMotorDirectionPin = leftDirection_pin;

	// Set up pins for output
	pinMode(_leftMotorSpeedPin,     OUTPUT);
	pinMode(_leftMotorDirectionPin, OUTPUT);
}

void Motor::right(int speed) {
	// Simple check to make sure our speed does not exceed
	// the defined speed limits.
	if ( speed > maxSpeed ) {
		speed = maxSpeed;
	} else if ( speed < minSpeed ) {
		speed = minSpeed;
	}

	if ( speed < 0 ) {
		digitalWrite(_rightMotorDirectionPin, HIGH);
		analogWrite(_rightMotorSpeedPin, abs(speed));
	} else {
		digitalWrite(_rightMotorDirectionPin, LOW);
		analogWrite(_rightMotorSpeedPin, speed);
	}
}

void Motor::left(int speed) {
	if ( speed > maxSpeed ) {
		speed = maxSpeed;
	} else if ( speed < minSpeed ) {
		speed = minSpeed;
	}

	if ( speed < 0 ) {
		digitalWrite(_leftMotorDirectionPin, LOW);
		analogWrite(_leftMotorSpeedPin, abs(speed));
	} else {
		digitalWrite(_leftMotorDirectionPin, HIGH);
		analogWrite(_leftMotorSpeedPin, speed);
	}
}

// Our attack() method is a very simple function that will
// tell both motors to charge forward at full speed.
void Motor::attack() {
	right(maxSpeed);
	left(maxSpeed);
}

// Our abort() method is a very simple function that will
// tell both motors to reverse at full speed.
void Motor::abort() {
	right(minSpeed);
	left(minSpeed);
}
<|endoftext|>


<commit_before>
#include <synext.hpp>
#include "../ast/expr.hpp"
#include "../ast/ast.hpp"
#include "../parse/common.hpp"
#include "macro_rules.hpp"

class CMacroRulesExpander:
    public ExpandProcMacro
{
    bool    expand_early() const override { return true; }

    ::std::unique_ptr<TokenStream> expand(Span sp, const ::AST::Crate& crate, const ::std::string& ident, const TokenTree& tt, AST::Module& mod) override
    {
        if( ident == "" )
            ERROR(sp, E0000, "macro_rules! requires an identifier" );

        TTStream    lex(tt);
        auto mac = Parse_MacroRules(lex);
        mod.add_macro( false, ident, mac );

        return box$( TTStreamO(TokenTree()) );
    }
};

class CMacroUseHandler:
    public ExpandDecorator
{
    AttrStage stage() const override { return AttrStage::EarlyPost; }

    void handle(const AST::MetaItem& mi, ::AST::Crate& crate, const AST::Path& path, AST::Module& mod, AST::Item& i) const override
    {
        TRACE_FUNCTION_F("path=" << path);
        if( !i.is_Module() )
            throw ::std::runtime_error("ERROR: Use of #[macro_use] on non-module");

        const auto& submod = i.as_Module().e;

        if( mi.has_sub_items() )
        {
            throw ::std::runtime_error("TODO: #[macro_use]");
        }
        else
        {
            for( const auto& mr : submod.macros() )
            {
                DEBUG("Imported " << mr.name);
                mod.add_macro_import( mr.name, mr.data );
            }
            for( const auto& mri : submod.macro_imports_res() )
            {
                DEBUG("Imported " << mri.name << " (propagate)");
                mod.add_macro_import( mri.name, *mri.data );
            }
        }
    }

};

::std::unique_ptr<TokenStream>  Macro_Invoke(const char* name, const MacroRules& rules, const TokenTree& tt, AST::Module& mod)
{
    return Macro_InvokeRules(name, rules, tt);
}

STATIC_MACRO("macro_rules", CMacroRulesExpander);
STATIC_DECORATOR("macro_use", CMacroUseHandler);

<commit_msg>Expand - macro_use with ident list<commit_after>
#include <synext.hpp>
#include "../ast/expr.hpp"
#include "../ast/ast.hpp"
#include "../parse/common.hpp"
#include "macro_rules.hpp"

class CMacroRulesExpander:
    public ExpandProcMacro
{
    bool    expand_early() const override { return true; }

    ::std::unique_ptr<TokenStream> expand(Span sp, const ::AST::Crate& crate, const ::std::string& ident, const TokenTree& tt, AST::Module& mod) override
    {
        if( ident == "" )
            ERROR(sp, E0000, "macro_rules! requires an identifier" );

        TTStream    lex(tt);
        auto mac = Parse_MacroRules(lex);
        mod.add_macro( false, ident, mac );

        return box$( TTStreamO(TokenTree()) );
    }
};

class CMacroUseHandler:
    public ExpandDecorator
{
    AttrStage stage() const override { return AttrStage::EarlyPost; }

    void handle(const AST::MetaItem& mi, ::AST::Crate& crate, const AST::Path& path, AST::Module& mod, AST::Item& i) const override
    {
        TRACE_FUNCTION_F("path=" << path);
        if( !i.is_Module() )
            throw ::std::runtime_error("ERROR: Use of #[macro_use] on non-module");

        const auto& submod = i.as_Module().e;

        if( mi.has_sub_items() )
        {
            for( const auto& si : mi.items() )
            {
                const auto& name = si.name();
                for( const auto& mr : submod.macros() )
                {
                    if( mr.name == name ) {
                        DEBUG("Imported " << mr.name);
                        mod.add_macro_import( mr.name, mr.data );
                        goto _good;
                    }
                }
                for( const auto& mri : submod.macro_imports_res() )
                {
                    if( mri.name == name ) {
                        DEBUG("Imported " << mri.name << " (propagate)");
                        mod.add_macro_import( mri.name, *mri.data );
                        goto _good;
                    }
                }
                ERROR(Span(), E0000, "Couldn't find macro " << name);
            _good:
                (void)0;
            }
        }
        else
        {
            for( const auto& mr : submod.macros() )
            {
                DEBUG("Imported " << mr.name);
                mod.add_macro_import( mr.name, mr.data );
            }
            for( const auto& mri : submod.macro_imports_res() )
            {
                DEBUG("Imported " << mri.name << " (propagate)");
                mod.add_macro_import( mri.name, *mri.data );
            }
        }
    }

};

::std::unique_ptr<TokenStream>  Macro_Invoke(const char* name, const MacroRules& rules, const TokenTree& tt, AST::Module& mod)
{
    return Macro_InvokeRules(name, rules, tt);
}

STATIC_MACRO("macro_rules", CMacroRulesExpander);
STATIC_DECORATOR("macro_use", CMacroUseHandler);

<|endoftext|>


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

  Program:   ORFEO Toolbox
  Language:  C++
  Date:      $Date$
  Version:   $Revision$

  Copyright (c) Centre National d'Etudes Spatiales. All rights reserved.
  See OTBCopyright.txt for details.

     This software is distributed WITHOUT ANY WARRANTY; without even
     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
     PURPOSE.  See the above copyright notices for more information.

=========================================================================*/

#include "otbVectorImage.h"
#include "otbImageFileReader.h"
#include <otbImageKeywordlist.h>
#include <iostream>
#include <sstream>
#include <iterator>

double convertToDouble(const std::string& s)
{
  std::istringstream i(s);
  double x;
  i >> x;
  return x;
}

int otbTestImageKeywordlist(int argc, char* argv[])
{

  if (argc != 6)
  {
    std::cout << argv[0]
              << " <input img filename> <input needed keyword list> <input list of tols for each needed kw> "
              <<" <output kw list filename> <bool test all kw>" << std::endl;

    return EXIT_FAILURE;
  }

  const unsigned int Dimension = 2;
  typedef double InputPixelType;
  typedef otb::VectorImage<InputPixelType, Dimension>  InputImageType;
  typedef otb::ImageFileReader<InputImageType>  ReaderType;

  const char*        inputFilename = argv[1];
  std::istringstream issNeededKw(argv[2]);
  std::istringstream issTols(argv[3]);
  char * outGeomFilename = argv[4];
  bool checkAllKw = argv[5];

  ReaderType::Pointer reader = ReaderType::New();
  reader->SetFileName(inputFilename);
  reader->UpdateOutputInformation();

  otb::ImageKeywordlist kwlist = reader->GetOutput()->GetImageKeywordlist();

  if (!(kwlist.GetSize() > 0))
  {
       std::cerr<<"Error : imageKeywordlist is empty."<<std::endl;
       return EXIT_FAILURE;
  }

  typedef otb::ImageKeywordlist::KeywordlistMap KeywordlistMapType;
  KeywordlistMapType kwmap = kwlist.GetKeywordlist();

  if (checkAllKw) // Check all keywords (ignore argv[2] and argv[3])
  {

	  // Write keywordlist, read it, compare it to the original list
	  WriteGeometry(kwlist,outGeomFilename);
	  otb::ImageKeywordlist kwlist2 = otb::ReadGeometryFromGEOMFile(outGeomFilename);
	  KeywordlistMapType kwmap2 = kwlist2.GetKeywordlist();

	  if (kwmap.size() != kwmap2.size() )
	  {
		std::cerr << "Error : keyword lists don't have the same size (orig / reloaded): " << kwmap.size() << " / " << kwmap2.size() << std::endl;
		return EXIT_FAILURE;
	  }

	  KeywordlistMapType::iterator kwlistIt = kwmap.begin();

	  double val1,val2;
	  while ( kwlistIt!=kwmap.end() )
	  {
		  val1 = convertToDouble(kwlistIt->second);

		  KeywordlistMapType::iterator it = kwmap2.find(kwlistIt->first);
		  if (it != kwmap2.end() )
		  {
		    val2 = convertToDouble(it->second);
		  }
		  else
		  {
		     std::cerr << "Error : couldn't find key " << kwlistIt->first << " in reloaded keyword list." << std::endl;
			 return EXIT_FAILURE;
		  }
		  if ( fabs( val2 - val1 ) > 0.01 )
				{
					std::cerr << "Error : orig key/value (" << kwlistIt->first << " " << kwlistIt->second << ")"<< std::endl
					    << "reloaded key/value (" << kwlistIt->first << " " << kwmap2[kwlistIt->first] << ")"<< std::endl;
					return EXIT_FAILURE;
				}
		  ++kwlistIt;
	  }

  }
  else // Check only needed keywords
  {
	  // #1 keywordlist, only check the needed keywords
	  /*-------------------------------------*/

	  //Split the string into many tokens, with whitespaces as separators
	  std::list<std::string> neededKw;
	  copy(std::istream_iterator<std::string>(issNeededKw),
		 std::istream_iterator<std::string>(),
		 back_inserter(neededKw));

	  std::list<std::string> missingKw;
	  for(std::list<std::string>::iterator neededIt=neededKw.begin(); neededIt!=neededKw.end(); ++neededIt)
	  {
		bool foundNeededKw = false;
		for(KeywordlistMapType::iterator kwlistIt=kwmap.begin(); kwlistIt!=kwmap.end(); ++kwlistIt)
		{
			std::size_t found = kwlistIt->first.find(*neededIt);
			if (found!=std::string::npos)
			{
				foundNeededKw = true;
			}
		}

		if (!foundNeededKw)
			missingKw.push_back(*neededIt);
	  }

	  if ( (neededKw.size()>0) && (missingKw.size()>0) )
	  {
		std::cerr << "Error : some keywords were not found; missing keywords : " << std::endl;
		for (std::list<std::string>::iterator itm = missingKw.begin(); itm != missingKw.end(); ++itm)
		   std::cerr << *itm << std::endl;
		return EXIT_FAILURE;
	  }
	  /*-------------------------------------*/

	  // #2 Write keywordlist, read it, compare it to the original list
	  WriteGeometry(kwlist,outGeomFilename);
	  otb::ImageKeywordlist kwlist2 = otb::ReadGeometryFromGEOMFile(outGeomFilename);
	  KeywordlistMapType kwmap2 = kwlist2.GetKeywordlist();

	  //Split the string into many tokens, with whitespaces as separators
	  std::list<std::string> tols;
	  copy(std::istream_iterator<std::string>(issTols),
		 std::istream_iterator<std::string>(),
		 back_inserter(tols));

	  if (tols.size() != neededKw.size() )
	  {
		std::cerr << "Error : needed keywords list should have the same size as the tolerances one (needed / tols): "
		          << neededKw.size() << " " << tols.size() << std::endl;
		return EXIT_FAILURE;
	  }

	  std::map<std::string,double> mapKwTol;
	  std::pair<std::map<std::string,double>::iterator,bool> ret;
	  std::list<std::string>::iterator tolsIt=tols.begin();
	  std::list<std::string>::iterator neededKwIt=neededKw.begin();
	  while ( (tolsIt!=tols.end()) && (neededKwIt!=neededKw.end()) )
	  {
	     mapKwTol.insert(  std::pair<std::string,double>(*neededKwIt,  convertToDouble(*tolsIt) )   );
	     ++tolsIt;
	     ++neededKwIt;
	  }

	  if (kwmap.size() != kwmap2.size() )
	  {
		std::cerr << "Error : keyword lists don't have the same size (orig / reloaded): " << kwmap.size() << " / " << kwmap2.size() << std::endl;
		return EXIT_FAILURE;
	  }

	  for(std::list<std::string>::iterator neededIt=neededKw.begin(); neededIt!=neededKw.end(); ++neededIt)
	  {
		KeywordlistMapType::iterator kwlistIt = kwmap.begin();
		KeywordlistMapType::iterator kwlistIt2 = kwmap2.begin();

		while ( (kwlistIt!=kwmap.end()) && (kwlistIt2!=kwmap2.end()) )
		{
			std::size_t found = kwlistIt->first.find(*neededIt);
			if (found!=std::string::npos) // keyword found
			{

				if ( fabs( convertToDouble(kwlistIt->second) - convertToDouble(kwlistIt2->second)) > mapKwTol[*neededIt] )
				{
					std::cerr << "Error : orig key/value (" << kwlistIt->first << " " << kwlistIt->second << ")"<< std::endl
					    << "reloaded key/value (" << kwlistIt2->first << " " << kwlistIt2->second << ")"<< std::endl;
					return EXIT_FAILURE;
				}

			}

			++kwlistIt;
			++kwlistIt2;
		}
	  }
  }
  return EXIT_SUCCESS;
}

<commit_msg>BUG: fixed a pb concerning string to double conversion (green dashboard)<commit_after>/*=========================================================================

  Program:   ORFEO Toolbox
  Language:  C++
  Date:      $Date$
  Version:   $Revision$

  Copyright (c) Centre National d'Etudes Spatiales. All rights reserved.
  See OTBCopyright.txt for details.

     This software is distributed WITHOUT ANY WARRANTY; without even
     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
     PURPOSE.  See the above copyright notices for more information.

=========================================================================*/

#include "otbVectorImage.h"
#include "otbImageFileReader.h"
#include <otbImageKeywordlist.h>
#include <iostream>
#include <sstream>
#include <iterator>

double convertStringToDouble(const std::string& s)
{
   std::istringstream i(s);
   double x;
   if (!(i >> x))
     return 0;
   return x;
}

int otbTestImageKeywordlist(int argc, char* argv[])
{

  if (argc != 6)
  {
    std::cout << argv[0]
              << " <input img filename> <input needed keyword list> <input list of tols for each needed kw> "
              <<" <output kw list filename> <bool test all kw>" << std::endl;

    return EXIT_FAILURE;
  }

  const unsigned int Dimension = 2;
  typedef double InputPixelType;
  typedef otb::VectorImage<InputPixelType, Dimension>  InputImageType;
  typedef otb::ImageFileReader<InputImageType>  ReaderType;

  const char*        inputFilename = argv[1];
  std::istringstream issNeededKw(argv[2]);
  std::istringstream issTols(argv[3]);
  char * outGeomFilename = argv[4];
  bool checkAllKw = argv[5];

  ReaderType::Pointer reader = ReaderType::New();
  reader->SetFileName(inputFilename);
  reader->UpdateOutputInformation();

  otb::ImageKeywordlist kwlist = reader->GetOutput()->GetImageKeywordlist();

  if (!(kwlist.GetSize() > 0))
  {
       std::cerr<<"Error : imageKeywordlist is empty."<<std::endl;
       return EXIT_FAILURE;
  }

  typedef otb::ImageKeywordlist::KeywordlistMap KeywordlistMapType;
  KeywordlistMapType kwmap = kwlist.GetKeywordlist();

  if (checkAllKw) // Check all keywords (ignore argv[2] and argv[3])
  {

	  // Write keywordlist, read it, compare it to the original list
	  WriteGeometry(kwlist,outGeomFilename);
	  otb::ImageKeywordlist kwlist2 = otb::ReadGeometryFromGEOMFile(outGeomFilename);
	  KeywordlistMapType kwmap2 = kwlist2.GetKeywordlist();

	  if (kwmap.size() != kwmap2.size() )
	  {
		std::cerr << "Error : keyword lists don't have the same size (orig / reloaded): " << kwmap.size() << " / " << kwmap2.size() << std::endl;
		return EXIT_FAILURE;
	  }

	  KeywordlistMapType::iterator kwlistIt = kwmap.begin();

	  double val1,val2;
	  while ( kwlistIt!=kwmap.end() )
	  {
		  val1 = convertStringToDouble(kwlistIt->second);

		  KeywordlistMapType::iterator it = kwmap2.find(kwlistIt->first);
		  if (it != kwmap2.end() )
		  {
		    val2 = convertStringToDouble(it->second);
		  }
		  else
		  {
		     std::cerr << "Error : couldn't find key " << kwlistIt->first << " in reloaded keyword list." << std::endl;
			 return EXIT_FAILURE;
		  }
		  if ( fabs( val2 - val1 ) > 0.01 )
				{
					std::cerr << "Error : orig key/value (" << kwlistIt->first << " " << kwlistIt->second << ")"<< std::endl
					    << "reloaded key/value (" << kwlistIt->first << " " << kwmap2[kwlistIt->first] << ")"<< std::endl;
					return EXIT_FAILURE;
				}
		  ++kwlistIt;
	  }

  }
  else // Check only needed keywords
  {
	  // #1 keywordlist, only check the needed keywords
	  /*-------------------------------------*/

	  //Split the string into many tokens, with whitespaces as separators
	  std::list<std::string> neededKw;
	  copy(std::istream_iterator<std::string>(issNeededKw),
		 std::istream_iterator<std::string>(),
		 back_inserter(neededKw));

	  std::list<std::string> missingKw;
	  for(std::list<std::string>::iterator neededIt=neededKw.begin(); neededIt!=neededKw.end(); ++neededIt)
	  {
		bool foundNeededKw = false;
		for(KeywordlistMapType::iterator kwlistIt=kwmap.begin(); kwlistIt!=kwmap.end(); ++kwlistIt)
		{
			std::size_t found = kwlistIt->first.find(*neededIt);
			if (found!=std::string::npos)
			{
				foundNeededKw = true;
			}
		}

		if (!foundNeededKw)
			missingKw.push_back(*neededIt);
	  }

	  if ( (neededKw.size()>0) && (missingKw.size()>0) )
	  {
		std::cerr << "Error : some keywords were not found; missing keywords : " << std::endl;
		for (std::list<std::string>::iterator itm = missingKw.begin(); itm != missingKw.end(); ++itm)
		   std::cerr << *itm << std::endl;
		return EXIT_FAILURE;
	  }
	  /*-------------------------------------*/

	  // #2 Write keywordlist, read it, compare it to the original list
	  WriteGeometry(kwlist,outGeomFilename);
	  otb::ImageKeywordlist kwlist2 = otb::ReadGeometryFromGEOMFile(outGeomFilename);
	  KeywordlistMapType kwmap2 = kwlist2.GetKeywordlist();

	  //Split the string into many tokens, with whitespaces as separators
	  std::list<std::string> tols;
	  copy(std::istream_iterator<std::string>(issTols),
		 std::istream_iterator<std::string>(),
		 back_inserter(tols));

	  if (tols.size() != neededKw.size() )
	  {
		std::cerr << "Error : needed keywords list should have the same size as the tolerances one (needed / tols): "
		          << neededKw.size() << " " << tols.size() << std::endl;
		return EXIT_FAILURE;
	  }

	  std::map<std::string,double> mapKwTol;
	  std::pair<std::map<std::string,double>::iterator,bool> ret;
	  std::list<std::string>::iterator tolsIt=tols.begin();
	  std::list<std::string>::iterator neededKwIt=neededKw.begin();
	  while ( (tolsIt!=tols.end()) && (neededKwIt!=neededKw.end()) )
	  {
	     mapKwTol.insert(  std::pair<std::string,double>(*neededKwIt,  convertStringToDouble(*tolsIt) )   );
	     ++tolsIt;
	     ++neededKwIt;
	  }

	  if (kwmap.size() != kwmap2.size() )
	  {
		std::cerr << "Error : keyword lists don't have the same size (orig / reloaded): " << kwmap.size() << " / " << kwmap2.size() << std::endl;
		return EXIT_FAILURE;
	  }

	  for(std::list<std::string>::iterator neededIt=neededKw.begin(); neededIt!=neededKw.end(); ++neededIt)
	  {
		KeywordlistMapType::iterator kwlistIt = kwmap.begin();
		KeywordlistMapType::iterator kwlistIt2 = kwmap2.begin();

		while ( (kwlistIt!=kwmap.end()) && (kwlistIt2!=kwmap2.end()) )
		{
			std::size_t found = kwlistIt->first.find(*neededIt);
			if (found!=std::string::npos) // keyword found
			{

				if ( fabs( convertStringToDouble(kwlistIt->second) - convertStringToDouble(kwlistIt2->second)) > mapKwTol[*neededIt] )
				{
					std::cerr << "Error : orig key/value (" << kwlistIt->first << " " << kwlistIt->second << ")"<< std::endl
					    << "reloaded key/value (" << kwlistIt2->first << " " << kwlistIt2->second << ")"<< std::endl;
					return EXIT_FAILURE;
				}

			}

			++kwlistIt;
			++kwlistIt2;
		}
	  }
  }
  return EXIT_SUCCESS;
}

<|endoftext|>


<commit_before>/*
 * nt loader
 *
 * Copyright 2006-2008 Mike McCormack
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library 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
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
 */

#include "config.h"

#include <unistd.h>
#include <fcntl.h>
#include <stdio.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/mman.h>
#include <sys/time.h>
#include <assert.h>

#include <sys/wait.h>
#include <sched.h>

#include <sys/ptrace.h>
#ifdef HAVE_ASM_PTRACE_H
#include <asm/ptrace.h>
#endif

#include "windef.h"
#include "winnt.h"
#include "mem.h"
#include "thread.h"

#include "ptrace_if.h"
#include "debug.h"
#include "platform.h"

#include "client.h"
#include "ptrace_base.h"

class tt_address_space_impl: public ptrace_address_space_impl
{
	enum stub_state {
		stub_running,
		stub_suspended,
	};
	long stub_regs[FRAME_SIZE];
	char buffer[64]; // same size as tt stub's buffer
	stub_state state;
	int in_fd;
	int out_fd;
	pid_t child_pid;
protected:
	//int ptrace_run( PCONTEXT ctx, int single_step );
	int readwrite( struct tt_req *req );
	void run_stub();
	void suspend();
public:
	static pid_t create_tracee( int& in_fd, int& out_fd );
	tt_address_space_impl( pid_t pid, int in_fd, int out_fd );
	virtual pid_t get_child_pid();
	virtual ~tt_address_space_impl();
	virtual int mmap( BYTE *address, size_t length, int prot, int flags, int file, off_t offset );
	virtual int munmap( BYTE *address, size_t length );
	virtual void run( void *TebBaseAddress, PCONTEXT ctx, int single_step, LARGE_INTEGER& timeout, execution_context_t *exec );
	virtual unsigned short get_userspace_fs();
};

pid_t tt_address_space_impl::get_child_pid()
{
	return child_pid;
}

pid_t tt_address_space_impl::create_tracee( int& in_fd, int& out_fd )
{
	int r;
	pid_t pid;
	int infds[2], outfds[2];

	r = pipe( infds );
	if (r != 0)
		return 0;

	r = pipe( outfds );
	if (r != 0)
		return 0;

	pid = fork();
	if (pid == -1)
		return pid;
	if (pid == 0)
	{
		// close stdin and stdout
		close(0);
		close(1);

		dup2( infds[0], STDIN_FILENO );
		close( infds[1] );

		dup2( outfds[1], STDOUT_FILENO );
		close( outfds[0] );

		::ptrace( PTRACE_TRACEME, 0, 0, 0 );
		r = ::execl("./ttclient", "./ttclient", NULL );
		// the next line should not be reached
		die("exec failed %d\n", r);
	}

	close( infds[0] );
	close( outfds[1] );
	in_fd = infds[1];
	out_fd = outfds[0];

	// wait for the child
	int status;
	if (pid != wait4( pid, &status, WUNTRACED, NULL ))
		return -1;

	r = ::ptrace( PTRACE_CONT, pid, 0, 0 );

	// read a single character from the stub to synchronize
	do {
		char dummy;
		r = read(out_fd, &dummy, 1);
	} while (r == -1 && errno == EINTR);

	//fprintf(stderr, "created process %d\n", pid );

	return pid;
}

tt_address_space_impl::tt_address_space_impl(pid_t pid, int in, int out) :
	state(stub_running),
	in_fd(in),
	out_fd(out),
	child_pid(pid)
{
	//dprintf("tt_address_space_impl()\n");
}

tt_address_space_impl::~tt_address_space_impl()
{
	assert( sig_target == 0 );
	//dprintf(stderr,"~tt_address_space_impl()\n");
	destroy();
	ptrace( PTRACE_KILL, child_pid, 0, 0 );
	assert( child_pid != -1 );
	kill( child_pid, SIGTERM );
	child_pid = -1;
}

address_space_impl* create_tt_address_space()
{
	//dprintf("create_tt_address_space\n");
	// Set up the signal handler and unmask it first.
	// The child's signal handler will be unmasked too.
	int in_fd = -1, out_fd = -1;
	pid_t pid = tt_address_space_impl::create_tracee( in_fd, out_fd );
	if (pid < 0)
		return 0;

	return new tt_address_space_impl( pid, in_fd, out_fd );
}

int tt_address_space_impl::readwrite( struct tt_req *req )
{
	int r;

	// getting a signal here can deadlock
	assert( sig_target == 0 );

	// send the buffer to the stub
	do {
		r = write(in_fd, req, sizeof *req);
	} while (r == -1 && errno == EINTR);
	if (r != sizeof *req)
	{
		fprintf(stderr, "write failed %d\n", r);
		return r;
	}

	// read the stub's response
	struct tt_reply reply;
	do {
		r = read(out_fd, &reply, sizeof reply);
	} while (r == -1 && errno == EINTR);
	if (r != sizeof reply)
	{
		fprintf(stderr, "read failed\n");
		return r;
	}

	return reply.r;
}

int tt_address_space_impl::mmap( BYTE *address, size_t length, int prot, int flags, int file, off_t offset )
{
	//dprintf("tt_address_space_impl::mmap()\n");
	run_stub();

	struct tt_req req;
	struct tt_req_map &map = req.u.map;

	req.type = tt_req_map;
	map.pid = getpid();
	map.fd = file;
	map.addr = (int) address;
	map.len = length;
	map.ofs = offset;
	map.prot = prot;
	// send our pid to the stub
	//dprintf("tt_address_space_impl::mmap()\n");
	return readwrite( &req );
}

int tt_address_space_impl::munmap( BYTE *address, size_t length )
{
	//dprintf("tt_address_space_impl::munmap()\n");
	run_stub();
	struct tt_req req;
	struct tt_req_umap &umap = req.u.umap;

	req.type = tt_req_umap;
	umap.addr = (int) address;
	umap.len = length;

	return readwrite( &req );
}

void tt_address_space_impl::run( void *TebBaseAddress, PCONTEXT ctx, int single_step, LARGE_INTEGER& timeout, execution_context_t *exec )
{
	//dprintf("tt_address_space_impl::run()\n");

	suspend();
	ptrace_address_space_impl::run( TebBaseAddress, ctx, single_step, timeout, exec );
}

unsigned short tt_address_space_impl::get_userspace_fs()
{
	suspend();
	return stub_regs[FS];
}

void tt_address_space_impl::suspend()
{
	if (state == stub_suspended)
		return;

	// no signals!
	assert( sig_target == 0 );

	assert( child_pid != -1 );
	kill( child_pid, SIGSTOP );

	while (1)
	{
		int status;
		pid_t pid = wait4( child_pid, &status, WUNTRACED, NULL );
		if (pid < 0)
			die("wait failed\n");
		if (pid != child_pid)
			continue;
		if (WIFEXITED(status) )
			die("Client died\n");

		if (WIFSTOPPED(status) && WEXITSTATUS(status) == SIGSTOP)
		{
			break;
		}
		dprintf("stray signal %d\n", WEXITSTATUS(status));

		// start the child again so we can get the next signal
		ptrace( PTRACE_CONT, child_pid, 0, 0 );
	}

	if (state == stub_running)
	{
		//dprintf("saving registers\n");
		int r = ptrace_get_regs( child_pid, stub_regs );
		if (r < 0)
			die("failed to save stub registers\n");
	}

	state = stub_suspended;
}

void tt_address_space_impl::run_stub()
{
	int r;
	suspend();
	r = ptrace_set_regs( child_pid, stub_regs );
	if (r < 0)
		die("ptrace_set_regs failed\n");
	r = ::ptrace( PTRACE_CONT, child_pid, 0, 0 );
	if (r < 0)
		die("ptrace( PTRACE_CONT ) failed\n");
	state = stub_running;
}

bool init_tt()
{
	dprintf("using tt\n");
	ptrace_address_space_impl::set_signals();
	pcreate_address_space = &create_tt_address_space;
	return true;
}
<commit_msg>Wait for signals properly<commit_after>/*
 * nt loader
 *
 * Copyright 2006-2008 Mike McCormack
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library 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
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
 */

#include "config.h"

#include <unistd.h>
#include <fcntl.h>
#include <stdio.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/mman.h>
#include <sys/time.h>
#include <assert.h>

#include <sys/wait.h>
#include <sched.h>

#include <sys/ptrace.h>
#ifdef HAVE_ASM_PTRACE_H
#include <asm/ptrace.h>
#endif

#include "windef.h"
#include "winnt.h"
#include "mem.h"
#include "thread.h"

#include "ptrace_if.h"
#include "debug.h"
#include "platform.h"

#include "client.h"
#include "ptrace_base.h"

class tt_address_space_impl: public ptrace_address_space_impl
{
	enum stub_state {
		stub_running,
		stub_suspended,
	};
	long stub_regs[FRAME_SIZE];
	char buffer[64]; // same size as tt stub's buffer
	stub_state state;
	int in_fd;
	int out_fd;
	pid_t child_pid;
protected:
	//int ptrace_run( PCONTEXT ctx, int single_step );
	int readwrite( struct tt_req *req );
	void run_stub();
	void suspend();
public:
	static void wait_for_signal( pid_t pid, int signal );
	static pid_t create_tracee( int& in_fd, int& out_fd );
	tt_address_space_impl( pid_t pid, int in_fd, int out_fd );
	virtual pid_t get_child_pid();
	virtual ~tt_address_space_impl();
	virtual int mmap( BYTE *address, size_t length, int prot, int flags, int file, off_t offset );
	virtual int munmap( BYTE *address, size_t length );
	virtual void run( void *TebBaseAddress, PCONTEXT ctx, int single_step, LARGE_INTEGER& timeout, execution_context_t *exec );
	virtual unsigned short get_userspace_fs();
};

pid_t tt_address_space_impl::get_child_pid()
{
	return child_pid;
}

void tt_address_space_impl::wait_for_signal( pid_t pid, int signal )
{
	while (1)
	{
		int r, status = 0;
		r = wait4( pid, &status, WUNTRACED, NULL );
		if (r < 0)
			die("wait_for_signal: wait4() failed %d\n", errno);
		if (r != pid)
			continue;
		if (WIFEXITED(status) )
			die("Client died\n");

		if (WIFSTOPPED(status) && WEXITSTATUS(status) == signal)
			return;

		dprintf("stray signal %d\n", WEXITSTATUS(status));

		// start the child again so we can get the next signal
		ptrace( PTRACE_CONT, pid, 0, 0 );
	}
}

pid_t tt_address_space_impl::create_tracee( int& in_fd, int& out_fd )
{
	int r;
	pid_t pid;
	int infds[2], outfds[2];

	r = pipe( infds );
	if (r != 0)
		return -1;

	r = pipe( outfds );
	if (r != 0)
		return -1;

	pid = fork();
	if (pid == -1)
	{
		dprintf("fork() failed %d\n", errno);
		return pid;
	}
	if (pid == 0)
	{
		// close stdin and stdout
		close(0);
		close(1);

		dup2( infds[0], STDIN_FILENO );
		close( infds[1] );

		dup2( outfds[1], STDOUT_FILENO );
		close( outfds[0] );

		::ptrace( PTRACE_TRACEME, 0, 0, 0 );
		r = ::execl("./ttclient", "./ttclient", NULL );
		// the next line should not be reached
		die("exec failed %d\n", r);
	}

	close( infds[0] );
	close( outfds[1] );
	in_fd = infds[1];
	out_fd = outfds[0];

	wait_for_signal( pid, SIGTRAP );

	r = ::ptrace( PTRACE_CONT, pid, 0, 0 );

	// read a single character from the stub to synchronize
	do {
		char dummy;
		r = read(out_fd, &dummy, 1);
	} while (r == -1 && errno == EINTR);

	//fprintf(stderr, "created process %d\n", pid );

	return pid;
}

tt_address_space_impl::tt_address_space_impl(pid_t pid, int in, int out) :
	state(stub_running),
	in_fd(in),
	out_fd(out),
	child_pid(pid)
{
	//dprintf("tt_address_space_impl()\n");
}

tt_address_space_impl::~tt_address_space_impl()
{
	assert( sig_target == 0 );
	//dprintf(stderr,"~tt_address_space_impl()\n");
	destroy();
	ptrace( PTRACE_KILL, child_pid, 0, 0 );
	assert( child_pid != -1 );
	kill( child_pid, SIGTERM );
	child_pid = -1;
}

address_space_impl* create_tt_address_space()
{
	//dprintf("create_tt_address_space\n");
	// Set up the signal handler and unmask it first.
	// The child's signal handler will be unmasked too.
	int in_fd = -1, out_fd = -1;
	pid_t pid = tt_address_space_impl::create_tracee( in_fd, out_fd );
	if (pid < 0)
		return 0;

	return new tt_address_space_impl( pid, in_fd, out_fd );
}

int tt_address_space_impl::readwrite( struct tt_req *req )
{
	int r;

	// getting a signal here can deadlock
	assert( sig_target == 0 );

	// send the buffer to the stub
	do {
		r = write(in_fd, req, sizeof *req);
	} while (r == -1 && errno == EINTR);
	if (r != sizeof *req)
	{
		fprintf(stderr, "write failed %d\n", r);
		return r;
	}

	// read the stub's response
	struct tt_reply reply;
	do {
		r = read(out_fd, &reply, sizeof reply);
	} while (r == -1 && errno == EINTR);
	if (r != sizeof reply)
	{
		fprintf(stderr, "read failed\n");
		return r;
	}

	return reply.r;
}

int tt_address_space_impl::mmap( BYTE *address, size_t length, int prot, int flags, int file, off_t offset )
{
	//dprintf("tt_address_space_impl::mmap()\n");
	run_stub();

	struct tt_req req;
	struct tt_req_map &map = req.u.map;

	req.type = tt_req_map;
	map.pid = getpid();
	map.fd = file;
	map.addr = (int) address;
	map.len = length;
	map.ofs = offset;
	map.prot = prot;
	// send our pid to the stub
	//dprintf("tt_address_space_impl::mmap()\n");
	return readwrite( &req );
}

int tt_address_space_impl::munmap( BYTE *address, size_t length )
{
	//dprintf("tt_address_space_impl::munmap()\n");
	run_stub();
	struct tt_req req;
	struct tt_req_umap &umap = req.u.umap;

	req.type = tt_req_umap;
	umap.addr = (int) address;
	umap.len = length;

	return readwrite( &req );
}

void tt_address_space_impl::run( void *TebBaseAddress, PCONTEXT ctx, int single_step, LARGE_INTEGER& timeout, execution_context_t *exec )
{
	//dprintf("tt_address_space_impl::run()\n");

	suspend();
	ptrace_address_space_impl::run( TebBaseAddress, ctx, single_step, timeout, exec );
}

unsigned short tt_address_space_impl::get_userspace_fs()
{
	suspend();
	return stub_regs[FS];
}

void tt_address_space_impl::suspend()
{
	if (state == stub_suspended)
		return;

	// no signals!
	assert( sig_target == 0 );

	assert( child_pid != -1 );
	kill( child_pid, SIGSTOP );

	wait_for_signal( child_pid, SIGSTOP );

	if (state == stub_running)
	{
		//dprintf("saving registers\n");
		int r = ptrace_get_regs( child_pid, stub_regs );
		if (r < 0)
			die("failed to save stub registers\n");
	}

	state = stub_suspended;
}

void tt_address_space_impl::run_stub()
{
	int r;
	suspend();
	r = ptrace_set_regs( child_pid, stub_regs );
	if (r < 0)
		die("ptrace_set_regs failed\n");
	r = ::ptrace( PTRACE_CONT, child_pid, 0, 0 );
	if (r < 0)
		die("ptrace( PTRACE_CONT ) failed\n");
	state = stub_running;
}

bool init_tt()
{
	dprintf("using tt\n");
	ptrace_address_space_impl::set_signals();
	pcreate_address_space = &create_tt_address_space;
	return true;
}
<|endoftext|>


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

 Program:   ORFEO Toolbox
 Language:  C++
 Date:      $Date$
 Version:   $Revision$

 Copyright (c) Centre National d'Etudes Spatiales. All rights reserved.
 See OTBCopyright.txt for details.

 This software is distributed WITHOUT ANY WARRANTY; without even
 the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
 PURPOSE.  See the above copyright notices for more information.

 =========================================================================*/
#include "otbWrapperApplication.h"
#include "otbWrapperApplicationFactory.h"

#include "otbStreamingMinMaxVectorImageFilter.h"
#include "otbVectorRescaleIntensityImageFilter.h"

namespace otb
{
namespace Wrapper
{

class Rescale : public Application
{
public:
  /** Standard class typedefs. */
  typedef Rescale                       Self;
  typedef Application                   Superclass;
  typedef itk::SmartPointer<Self>       Pointer;
  typedef itk::SmartPointer<const Self> ConstPointer;

  /** Standard macro */
  itkNewMacro(Self);

  itkTypeMacro(Rescale, otb::Application);

  /** Filters typedef */
  typedef otb::StreamingMinMaxVectorImageFilter<FloatVectorImageType>  MinMaxFilterType;
  typedef otb::VectorRescaleIntensityImageFilter<FloatVectorImageType> RescaleImageFilterType;

private:
   Rescale()
  {
    SetName("Rescale");
    SetDescription("Rescale the image between two given values.");
  }

  virtual ~Rescale()
  {
  }

  void DoCreateParameters()
  {
    AddParameter(ParameterType_InputImage,  "in",   "Input Image");
    AddParameter(ParameterType_OutputImage, "out",  "Output Image");

    AddParameter(ParameterType_Float,      "outmin", "Output min value");
    AddParameter(ParameterType_Float,      "outmax", "Output max value");
    SetParameterFloat("outmin", 0);
    SetParameterDescription( "outmin", "Minimum value of the output image." );
    SetParameterFloat("outmax", 255);
    SetParameterDescription( "outmax", "Maximum value of the output image." );

    MandatoryOff("outmin");
    MandatoryOff("outmax");
  }

  void DoUpdateParameters()
  {
    // Nothing to do here for the parameters : all are independent

    // Reinitialize the object
    m_RescaleFilter = RescaleImageFilterType::New();
    m_MinMaxFilter = MinMaxFilterType::New();
  }

  void DoExecute()
  {
    FloatVectorImageType::Pointer inImage = GetParameterImage("in");

    otbAppLogDEBUG( << "Starting Min/Max computation" )

    m_MinMaxFilter->GetStreamer()->SetNumberOfLinesStrippedStreaming( 50 );
    m_MinMaxFilter->SetInput( inImage );
    AddProcess(m_MinMaxFilter->GetStreamer(), "Min/Max computing");
    m_MinMaxFilter->Update();

    otbAppLogDEBUG( << "Min/Max computation done : min=" << m_MinMaxFilter->GetMinimum()
                    << " max=" << m_MinMaxFilter->GetMaximum() )

    FloatVectorImageType::PixelType inMin, inMax;

    m_RescaleFilter->SetInput( inImage );
    m_RescaleFilter->SetInputMinimum( m_MinMaxFilter->GetMinimum() );
    m_RescaleFilter->SetInputMaximum( m_MinMaxFilter->GetMaximum() );

    FloatVectorImageType::PixelType outMin, outMax;
    outMin.SetSize( inImage->GetNumberOfComponentsPerPixel() );
    outMax.SetSize( inImage->GetNumberOfComponentsPerPixel() );
    outMin.Fill( GetParameterFloat("outmin") );
    outMax.Fill( GetParameterFloat("outmax") );

    m_RescaleFilter->SetOutputMinimum( outMin );
    m_RescaleFilter->SetOutputMaximum( outMax );
    m_RescaleFilter->UpdateOutputInformation();

    SetParameterOutputImage("out", m_RescaleFilter->GetOutput());
  }

  RescaleImageFilterType::Pointer m_RescaleFilter;
  MinMaxFilterType::Pointer       m_MinMaxFilter;
};

}
}

OTB_APPLICATION_EXPORT(otb::Wrapper::Rescale)
<commit_msg>BUG: fix initialization of Rescale application<commit_after>/*=========================================================================

 Program:   ORFEO Toolbox
 Language:  C++
 Date:      $Date$
 Version:   $Revision$

 Copyright (c) Centre National d'Etudes Spatiales. All rights reserved.
 See OTBCopyright.txt for details.

 This software is distributed WITHOUT ANY WARRANTY; without even
 the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
 PURPOSE.  See the above copyright notices for more information.

 =========================================================================*/
#include "otbWrapperApplication.h"
#include "otbWrapperApplicationFactory.h"

#include "otbStreamingMinMaxVectorImageFilter.h"
#include "otbVectorRescaleIntensityImageFilter.h"

namespace otb
{
namespace Wrapper
{

class Rescale : public Application
{
public:
  /** Standard class typedefs. */
  typedef Rescale                       Self;
  typedef Application                   Superclass;
  typedef itk::SmartPointer<Self>       Pointer;
  typedef itk::SmartPointer<const Self> ConstPointer;

  /** Standard macro */
  itkNewMacro(Self);

  itkTypeMacro(Rescale, otb::Application);

  /** Filters typedef */
  typedef otb::StreamingMinMaxVectorImageFilter<FloatVectorImageType>  MinMaxFilterType;
  typedef otb::VectorRescaleIntensityImageFilter<FloatVectorImageType> RescaleImageFilterType;

private:
   Rescale()
  {
    SetName("Rescale");
    SetDescription("Rescale the image between two given values.");
  }

  virtual ~Rescale()
  {
  }

  void DoCreateParameters()
  {
    AddParameter(ParameterType_InputImage,  "in",   "Input Image");
    AddParameter(ParameterType_OutputImage, "out",  "Output Image");

    AddParameter(ParameterType_Float,      "outmin", "Output min value");
    AddParameter(ParameterType_Float,      "outmax", "Output max value");
    SetParameterFloat("outmin", 0);
    SetParameterDescription( "outmin", "Minimum value of the output image." );
    SetParameterFloat("outmax", 255);
    SetParameterDescription( "outmax", "Maximum value of the output image." );

    MandatoryOff("outmin");
    MandatoryOff("outmax");
  }

  void DoUpdateParameters()
  {
    // Nothing to do here for the parameters : all are independent
  }

  void DoExecute()
  {
    FloatVectorImageType::Pointer inImage = GetParameterImage("in");

    otbAppLogDEBUG( << "Starting Min/Max computation" )

    m_MinMaxFilter = MinMaxFilterType::New();
    m_MinMaxFilter->SetInput( inImage );
    m_MinMaxFilter->GetStreamer()->SetNumberOfLinesStrippedStreaming( 50 );

    AddProcess(m_MinMaxFilter->GetStreamer(), "Min/Max computing");
    m_MinMaxFilter->Update();

    otbAppLogDEBUG( << "Min/Max computation done : min=" << m_MinMaxFilter->GetMinimum()
                    << " max=" << m_MinMaxFilter->GetMaximum() )

    FloatVectorImageType::PixelType inMin, inMax;

    m_RescaleFilter = RescaleImageFilterType::New();
    m_RescaleFilter->SetInput( inImage );
    m_RescaleFilter->SetInputMinimum( m_MinMaxFilter->GetMinimum() );
    m_RescaleFilter->SetInputMaximum( m_MinMaxFilter->GetMaximum() );

    FloatVectorImageType::PixelType outMin, outMax;
    outMin.SetSize( inImage->GetNumberOfComponentsPerPixel() );
    outMax.SetSize( inImage->GetNumberOfComponentsPerPixel() );
    outMin.Fill( GetParameterFloat("outmin") );
    outMax.Fill( GetParameterFloat("outmax") );

    m_RescaleFilter->SetOutputMinimum( outMin );
    m_RescaleFilter->SetOutputMaximum( outMax );
    m_RescaleFilter->UpdateOutputInformation();

    SetParameterOutputImage("out", m_RescaleFilter->GetOutput());
  }

  RescaleImageFilterType::Pointer m_RescaleFilter;
  MinMaxFilterType::Pointer       m_MinMaxFilter;
};

}
}

OTB_APPLICATION_EXPORT(otb::Wrapper::Rescale)
<|endoftext|>