<commit_before>#include "kafka.h"
#include <iostream>
#include <librdkafka/rdkafkacpp.h>
#include <boost/asio/ip/host_name.hpp>

// XXX require the unused fields to be present but blank?
void set_single_config_field(RdKafka::Conf& rd_conf, YAML::Node& yaml_conf, std::string field) {
  if (!yaml_conf[field]) {
      print::debug("KafkaProducer: no config for ", field);
      throw;
  }

  if (yaml_conf[field].IsNull()) {
      return;
  }

  auto value = yaml_conf[field].as<std::string>();
  std::string errstr;
  if (rd_conf.set(field, value, errstr) !=
      RdKafka::Conf::CONF_OK) {
      print::debug("KafkaProducer: bad config for ", field, value, errstr);
    throw;
  }
}

KafkaProducer::KafkaProducer(BanjaxInterface* banjax, YAML::Node &config)
  : banjax(banjax) {
  print::debug("KafkaProducer default constructor");
  if (config.Type() != YAML::NodeType::Map) {
      print::debug("KafkaProducer::load_config requires a YAML::Map");
    throw;
  }

  auto conf = RdKafka::Conf::create(RdKafka::Conf::CONF_GLOBAL);

  set_single_config_field(*conf, config, "metadata.broker.list");
  set_single_config_field(*conf, config, "security.protocol");
  set_single_config_field(*conf, config, "ssl.ca.location");
  set_single_config_field(*conf, config, "ssl.certificate.location");
  set_single_config_field(*conf, config, "ssl.key.location");
  set_single_config_field(*conf, config, "ssl.key.password");

  report_topic = config["report_topic"].as<std::string>();

  std::string errstr;
  rdk_producer.reset(RdKafka::Producer::create(conf, errstr));
  if (!rdk_producer) {
      print::debug("KafkaProducer: failed to create Producer (for failed challenges): ", errstr);
    throw;
  }

  print::debug("KafkaProducer load_config done");
}

int KafkaProducer::send_message(const json& message) {
  const std::string& serialized_message = message.dump();
  size_t serialized_message_size = message.dump().size();

  RdKafka::ErrorCode err = rdk_producer->produce(
      /* Topic name */
      report_topic,
      /* Any Partition */
      (int)RdKafka::Topic::PARTITION_UA,
      /* Make a copy of the value */
      (int)RdKafka::Producer::RK_MSG_COPY /* Copy payload */,
      /* Value */
      (void*)serialized_message.c_str(), serialized_message_size,
      /* Key */
      nullptr, 0,
      /* Timestamp (defaults to current time) */
      0,
      /* Message headers, if any */
      NULL);
  if (err == RdKafka::ERR_NO_ERROR) {
      print::debug("sent message: ", serialized_message);
      return 0;
  } else {
      print::debug("Failed to send kafka message! ");
      return -1;
  }
}

void
KafkaConsumer::reload_config(YAML::Node& config, BanjaxInterface* new_banjax) {
    {
        TSMutexLock(stored_config_lock);
        auto on_scope_exit = defer([&] { TSMutexUnlock(stored_config_lock); });
        stored_config = config;
        banjax = new_banjax;
        config_valid = false;
    }
}

KafkaConsumer::KafkaConsumer(YAML::Node &new_config, BanjaxInterface* new_banjax)
  : stored_config_lock(TSMutexCreate()),
    stored_config(new_config),
    banjax(new_banjax)
{
    // XXX this (or at least the `while (config_valid && !shutting_down)` loop ~50 lines down)
    // should probably be a TS continuation scheduled with TSContScheduleEvery(),
    // but i think this thing below works and i'm afraid of breaking it.
    thread_handle = std::thread([=] {
        while (!shutting_down) {
            print::debug("kafka consumer is (re)loading configuration");
            auto conf = RdKafka::Conf::create(RdKafka::Conf::CONF_GLOBAL);
            // auto tconf = RdKafka::Conf::create(RdKafka::Conf::CONF_TOPIC);
            std::vector<std::string> topics;  // annoyingly a vector when we really just need one
            std::string errstr;
            {
                TSMutexLock(stored_config_lock);
                auto on_scope_exit = defer([&] { TSMutexUnlock(stored_config_lock); });
                if (stored_config.Type() != YAML::NodeType::Map) {
                    print::debug("KafkaConsumer::load_config requires a YAML::Map");
                    throw;
                }

                auto topic = stored_config["command_topic"].as<std::string>();
                topics.push_back(topic);

                set_single_config_field(*conf, stored_config, "metadata.broker.list");
                set_single_config_field(*conf, stored_config, "security.protocol");
                set_single_config_field(*conf, stored_config, "ssl.ca.location");
                set_single_config_field(*conf, stored_config, "ssl.certificate.location");
                set_single_config_field(*conf, stored_config, "ssl.key.location");
                set_single_config_field(*conf, stored_config, "ssl.key.password");

                // we want every banjax instance to see every message. this means every banjax instance
                // needs its own group id. so i'm using the hostname.
                if (conf->set("group.id", boost::asio::ip::host_name(), errstr) != RdKafka::Conf::CONF_OK) {
                    print::debug("KafkaConsumer: bad group.id config: ", errstr);
                    throw;
                }
                config_valid = true;
            }

            RdKafka::KafkaConsumer *consumer = RdKafka::KafkaConsumer::create(conf, errstr);
            if (!consumer) {
                print::debug("Failed to create consumer: ", errstr);
                throw;
            }

            print::debug("% Created consumer ", consumer->name());

            RdKafka::ErrorCode resp = consumer->subscribe(topics);
            if (resp != RdKafka::ERR_NO_ERROR) {
                print::debug("Failed to start consumer: ", RdKafka::err2str(resp));
                throw; // XXX inside this thread?...
            }

            while (config_valid && !shutting_down) {
                print::debug("kafka consumer is blocking...");
                auto msg = std::unique_ptr<RdKafka::Message>(consumer->consume(2000));
                msg_consume(std::move(msg), NULL);
            }

            consumer->close();
        }
    });
}

void KafkaConsumer::shutdown() {
  shutting_down = true;
  thread_handle.join();
  print::debug("KafkaConsumer::shutdown() after thread join");
}

void KafkaConsumer::msg_consume(std::unique_ptr<RdKafka::Message> message,
                                void *opaque) {
    if (TSMutexLockTry(stored_config_lock) != TS_SUCCESS) {
        print::debug(
            "KafkaConsumer::msg_consume() failed to get lock; skipping.");
        return;
    }
    print::debug("KafkaConsumer::msg_consume() acquired lock");
    {
        auto on_scope_exit = defer([&] { TSMutexUnlock(stored_config_lock); });
        print::debug("KafkaConsumer::msg_consume()");
        switch (message->err()) {
        case RdKafka::ERR__TIMED_OUT:
            print::debug("no message, just a timeout");
            break;

        case RdKafka::ERR_NO_ERROR: {
            /* Real message */
            print::debug("Read msg at offset ", message->offset());
            print::debug("msg json: ", (char *)message->payload());
            json message_dict;
            try {
                message_dict = json::parse((char *)message->payload());
            } catch (json::exception &e) {
                print::debug("kafka message not json: ",
                             (char *)message->payload());
                return;
            }

            banjax->kafka_message_consume(message_dict);
        } break;
        case RdKafka::ERR__PARTITION_EOF: {
            print::debug("%% EOF reached for all  partition(s)");
        } break;
        case RdKafka::ERR__UNKNOWN_TOPIC: {
        }
        case RdKafka::ERR__UNKNOWN_PARTITION: {
            print::debug("Consume failed: ", message->errstr());
        } break;
        default: {
            /* Errors */
            print::debug("Consume failed: ", message->errstr());
        }
        }
    }
    print::debug("KafkaConsumer::msg_consume() released lock");
}
<commit_msg>clean up switch statement<commit_after>#include "kafka.h"
#include <iostream>
#include <librdkafka/rdkafkacpp.h>
#include <boost/asio/ip/host_name.hpp>

// XXX require the unused fields to be present but blank?
void set_single_config_field(RdKafka::Conf& rd_conf, YAML::Node& yaml_conf, std::string field) {
  if (!yaml_conf[field]) {
      print::debug("KafkaProducer: no config for ", field);
      throw;
  }

  if (yaml_conf[field].IsNull()) {
      return;
  }

  auto value = yaml_conf[field].as<std::string>();
  std::string errstr;
  if (rd_conf.set(field, value, errstr) !=
      RdKafka::Conf::CONF_OK) {
      print::debug("KafkaProducer: bad config for ", field, value, errstr);
    throw;
  }
}

KafkaProducer::KafkaProducer(BanjaxInterface* banjax, YAML::Node &config)
  : banjax(banjax) {
  print::debug("KafkaProducer default constructor");
  if (config.Type() != YAML::NodeType::Map) {
      print::debug("KafkaProducer::load_config requires a YAML::Map");
    throw;
  }

  auto conf = RdKafka::Conf::create(RdKafka::Conf::CONF_GLOBAL);

  set_single_config_field(*conf, config, "metadata.broker.list");
  set_single_config_field(*conf, config, "security.protocol");
  set_single_config_field(*conf, config, "ssl.ca.location");
  set_single_config_field(*conf, config, "ssl.certificate.location");
  set_single_config_field(*conf, config, "ssl.key.location");
  set_single_config_field(*conf, config, "ssl.key.password");

  report_topic = config["report_topic"].as<std::string>();

  std::string errstr;
  rdk_producer.reset(RdKafka::Producer::create(conf, errstr));
  if (!rdk_producer) {
      print::debug("KafkaProducer: failed to create Producer (for failed challenges): ", errstr);
    throw;
  }

  print::debug("KafkaProducer load_config done");
}

int KafkaProducer::send_message(const json& message) {
  const std::string& serialized_message = message.dump();
  size_t serialized_message_size = message.dump().size();

  RdKafka::ErrorCode err = rdk_producer->produce(
      /* Topic name */
      report_topic,
      /* Any Partition */
      (int)RdKafka::Topic::PARTITION_UA,
      /* Make a copy of the value */
      (int)RdKafka::Producer::RK_MSG_COPY /* Copy payload */,
      /* Value */
      (void*)serialized_message.c_str(), serialized_message_size,
      /* Key */
      nullptr, 0,
      /* Timestamp (defaults to current time) */
      0,
      /* Message headers, if any */
      NULL);
  if (err == RdKafka::ERR_NO_ERROR) {
      print::debug("sent message: ", serialized_message);
      return 0;
  } else {
      print::debug("Failed to send kafka message! ");
      return -1;
  }
}

void
KafkaConsumer::reload_config(YAML::Node& config, BanjaxInterface* new_banjax) {
    {
        TSMutexLock(stored_config_lock);
        auto on_scope_exit = defer([&] { TSMutexUnlock(stored_config_lock); });
        stored_config = config;
        banjax = new_banjax;
        config_valid = false;
    }
}

KafkaConsumer::KafkaConsumer(YAML::Node &new_config, BanjaxInterface* new_banjax)
  : stored_config_lock(TSMutexCreate()),
    stored_config(new_config),
    banjax(new_banjax)
{
    // XXX this (or at least the `while (config_valid && !shutting_down)` loop ~50 lines down)
    // should probably be a TS continuation scheduled with TSContScheduleEvery(),
    // but i think this thing below works and i'm afraid of breaking it.
    thread_handle = std::thread([=] {
        while (!shutting_down) {
            print::debug("kafka consumer is (re)loading configuration");
            auto conf = RdKafka::Conf::create(RdKafka::Conf::CONF_GLOBAL);
            // auto tconf = RdKafka::Conf::create(RdKafka::Conf::CONF_TOPIC);
            std::vector<std::string> topics;  // annoyingly a vector when we really just need one
            std::string errstr;
            {
                TSMutexLock(stored_config_lock);
                auto on_scope_exit = defer([&] { TSMutexUnlock(stored_config_lock); });
                if (stored_config.Type() != YAML::NodeType::Map) {
                    print::debug("KafkaConsumer::load_config requires a YAML::Map");
                    throw;
                }

                auto topic = stored_config["command_topic"].as<std::string>();
                topics.push_back(topic);

                set_single_config_field(*conf, stored_config, "metadata.broker.list");
                set_single_config_field(*conf, stored_config, "security.protocol");
                set_single_config_field(*conf, stored_config, "ssl.ca.location");
                set_single_config_field(*conf, stored_config, "ssl.certificate.location");
                set_single_config_field(*conf, stored_config, "ssl.key.location");
                set_single_config_field(*conf, stored_config, "ssl.key.password");

                // we want every banjax instance to see every message. this means every banjax instance
                // needs its own group id. so i'm using the hostname.
                if (conf->set("group.id", boost::asio::ip::host_name(), errstr) != RdKafka::Conf::CONF_OK) {
                    print::debug("KafkaConsumer: bad group.id config: ", errstr);
                    throw;
                }
                config_valid = true;
            }

            RdKafka::KafkaConsumer *consumer = RdKafka::KafkaConsumer::create(conf, errstr);
            if (!consumer) {
                print::debug("Failed to create consumer: ", errstr);
                throw;
            }

            print::debug("% Created consumer ", consumer->name());

            RdKafka::ErrorCode resp = consumer->subscribe(topics);
            if (resp != RdKafka::ERR_NO_ERROR) {
                print::debug("Failed to start consumer: ", RdKafka::err2str(resp));
                throw; // XXX inside this thread?...
            }

            while (config_valid && !shutting_down) {
                print::debug("kafka consumer is blocking...");
                auto msg = std::unique_ptr<RdKafka::Message>(consumer->consume(2000));
                msg_consume(std::move(msg), NULL);
            }

            consumer->close();
        }
    });
}

void KafkaConsumer::shutdown() {
  shutting_down = true;
  thread_handle.join();
  print::debug("KafkaConsumer::shutdown() after thread join");
}

void KafkaConsumer::msg_consume(std::unique_ptr<RdKafka::Message> message,
                                void *opaque) {
    if (TSMutexLockTry(stored_config_lock) != TS_SUCCESS) {
        print::debug(
            "KafkaConsumer::msg_consume() failed to get lock; skipping.");
        return;
    }
    print::debug("KafkaConsumer::msg_consume() acquired lock");
    {
        auto on_scope_exit = defer([&] { TSMutexUnlock(stored_config_lock); });
        print::debug("KafkaConsumer::msg_consume()");
        switch (message->err()) {
        case RdKafka::ERR__TIMED_OUT: {
            print::debug("no message, just a timeout");
            break;
        }

        case RdKafka::ERR_NO_ERROR: {
            /* Real message */
            print::debug("Read msg at offset ", message->offset());
            print::debug("msg json: ", (char *)message->payload());
            json message_dict;
            try {
                message_dict = json::parse((char *)message->payload());
            } catch (json::exception &e) {
                print::debug("kafka message not json: ",
                             (char *)message->payload());
                return;
            }

            banjax->kafka_message_consume(message_dict);
            break;
        }

        case RdKafka::ERR__PARTITION_EOF: {
            print::debug("%% EOF reached for all  partition(s)");
            break;
        }

        case RdKafka::ERR__UNKNOWN_TOPIC: {
            break;
        }

        case RdKafka::ERR__UNKNOWN_PARTITION: {
            print::debug("Consume failed: ", message->errstr());
            break;
        }

        default: {
            /* Errors */
            print::debug("Consume failed: ", message->errstr());
            break;
        }

        }
    }
    print::debug("KafkaConsumer::msg_consume() released lock");
}
<|endoftext|>


<commit_before>/* Copyright (c) 2018 PaddlePaddle Authors. All Rights Reserved.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License. */

#include <glog/logging.h>
#include <gtest/gtest.h>
#include <cmath>
#include <mutex>   // NOLINT
#include <thread>  // NOLINT
#include "gflags/gflags.h"

#include "paddle/fluid/inference/tests/api/tester_helper.h"

namespace paddle {
namespace inference {

int test_predictor(const AnalysisConfig& config_in,
                   Barrier* barrier = nullptr) {
  static std::mutex mutex;
  AnalysisConfig config{config_in};
  std::unique_ptr<PaddlePredictor> predictor;
  {
    std::unique_lock<std::mutex> lock(mutex);
    predictor = std::move(CreatePaddlePredictor(config));
  }
  if (barrier) {
    barrier->Wait();
  }

  std::vector<PaddleTensor> inputs;
  std::vector<float> input({1});

  PaddleTensor in;
  in.shape = {1, 1};
  in.data = PaddleBuf(static_cast<void*>(input.data()), 1 * sizeof(float));
  in.dtype = PaddleDType::FLOAT32;
  inputs.emplace_back(in);

  std::vector<PaddleTensor> outputs;
  predictor->Run(inputs, &outputs);
  const std::vector<float> truth_values = {
      -0.00621776f, -0.00620937f, 0.00990623f,  -0.0039817f, -0.00074315f,
      0.61229795f,  -0.00491806f, -0.00068755f, 0.18409646f, 0.30090684f};
  const size_t expected_size = 1;
  EXPECT_EQ(outputs.size(), expected_size);
  float* data_o = static_cast<float*>(outputs[0].data.data());
  for (size_t j = 0; j < outputs[0].data.length() / sizeof(float); ++j) {
    EXPECT_LT(std::abs(data_o[j] - truth_values[j]), 10e-6);
  }
  return 0;
}

int test_predictor_zero_copy(const AnalysisConfig& config_in,
                             Barrier* barrier = nullptr) {
  static std::mutex mutex;
  AnalysisConfig config{config_in};
  config.SwitchUseFeedFetchOps(false);
  std::unique_ptr<PaddlePredictor> predictor;
  {
    std::unique_lock<std::mutex> lock(mutex);
    predictor = std::move(CreatePaddlePredictor(config));
  }
  if (barrier) {
    barrier->Wait();
  }

  std::vector<float> input({1});
  auto in_tensor{predictor->GetInputTensor(predictor->GetInputNames().front())};
  in_tensor->Reshape({1, 1});
  in_tensor->copy_from_cpu(input.data());

  predictor->ZeroCopyRun();

  auto out_tensor{
      predictor->GetOutputTensor(predictor->GetOutputNames().front())};
  std::vector<float> data_o(10);
  out_tensor->copy_to_cpu(data_o.data());

  const std::vector<float> truth_values = {
      -0.00621776f, -0.00620937f, 0.00990623f,  -0.0039817f, -0.00074315f,
      0.61229795f,  -0.00491806f, -0.00068755f, 0.18409646f, 0.30090684f};
  const size_t expected_size = 1;
  EXPECT_EQ(predictor->GetOutputNames().size(), expected_size);
  for (size_t j = 0; j < truth_values.size(); ++j) {
    EXPECT_LT(std::abs(data_o[j] - truth_values[j]), 10e-6);
  }
  return 0;
}

#ifdef PADDLE_WITH_XPU
TEST(AnalysisPredictor, native_xpu) {
  AnalysisConfig config;
  config.EnableXpu();
  config.SetModel(FLAGS_infer_model + "/" + "mul_model");
  test_predictor(config);
  test_predictor_zero_copy(config);
}
#endif

#ifdef LITE_SUBGRAPH_WITH_XPU
TEST(AnalysisPredictor, lite_xpu) {
  AnalysisConfig config;
  config.EnableXpu();
  config.SetModel(FLAGS_infer_model + "/" + "mul_model");
  config.EnableLiteEngine(paddle::AnalysisConfig::Precision::kFloat32);
  test_predictor(config);
  test_predictor_zero_copy(config);
}
#endif

#if defined(PADDLE_WITH_CUDA) || defined(PADDLE_WITH_HIP)
TEST(AnalysisPredictor, thread_local_stream) {
  const size_t thread_num = 5;
  std::vector<std::thread> threads(thread_num);
  Barrier barrier(thread_num);
  for (size_t i = 0; i < threads.size(); ++i) {
    threads[i] = std::thread([&barrier, i]() {
      AnalysisConfig config;
      config.EnableUseGpu(100, 0);
      config.SetModel(FLAGS_infer_model + "/" + "mul_model");
      config.EnableGpuMultiStream();
      test_predictor(config, &barrier);
      test_predictor_zero_copy(config);
    });
  }
  for (auto& th : threads) {
    th.join();
  }
}

TEST(AnalysisPredictor, lite_engine) {
  AnalysisConfig config;
  config.EnableUseGpu(100, 0);
  config.SetModel(FLAGS_infer_model + "/" + "mul_model");
  config.EnableLiteEngine(paddle::AnalysisConfig::Precision::kFloat32);
  test_predictor(config);
  test_predictor_zero_copy(config);
}
#endif

}  // namespace inference
}  // namespace paddle
<commit_msg>fix a syntax error, test=develop (#31930)<commit_after>/* Copyright (c) 2018 PaddlePaddle Authors. All Rights Reserved.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License. */

#include <glog/logging.h>
#include <gtest/gtest.h>
#include <cmath>
#include <mutex>   // NOLINT
#include <thread>  // NOLINT
#include "gflags/gflags.h"

#include "paddle/fluid/inference/tests/api/tester_helper.h"

namespace paddle {
namespace inference {

int test_predictor(const AnalysisConfig& config_in,
                   Barrier* barrier = nullptr) {
  static std::mutex mutex;
  AnalysisConfig config{config_in};
  std::unique_ptr<PaddlePredictor> predictor;
  {
    std::unique_lock<std::mutex> lock(mutex);
    predictor = std::move(CreatePaddlePredictor(config));
  }
  if (barrier) {
    barrier->Wait();
  }

  std::vector<PaddleTensor> inputs;
  std::vector<float> input({1});

  PaddleTensor in;
  in.shape = {1, 1};
  in.data = PaddleBuf(static_cast<void*>(input.data()), 1 * sizeof(float));
  in.dtype = PaddleDType::FLOAT32;
  inputs.emplace_back(in);

  std::vector<PaddleTensor> outputs;
  predictor->Run(inputs, &outputs);
  const std::vector<float> truth_values = {
      -0.00621776f, -0.00620937f, 0.00990623f,  -0.0039817f, -0.00074315f,
      0.61229795f,  -0.00491806f, -0.00068755f, 0.18409646f, 0.30090684f};
  const size_t expected_size = 1;
  EXPECT_EQ(outputs.size(), expected_size);
  float* data_o = static_cast<float*>(outputs[0].data.data());
  for (size_t j = 0; j < outputs[0].data.length() / sizeof(float); ++j) {
    EXPECT_LT(std::abs(data_o[j] - truth_values[j]), 10e-6);
  }
  return 0;
}

int test_predictor_zero_copy(const AnalysisConfig& config_in,
                             Barrier* barrier = nullptr) {
  static std::mutex mutex;
  AnalysisConfig config{config_in};
  config.SwitchUseFeedFetchOps(false);
  std::unique_ptr<PaddlePredictor> predictor;
  {
    std::unique_lock<std::mutex> lock(mutex);
    predictor = std::move(CreatePaddlePredictor(config));
  }
  if (barrier) {
    barrier->Wait();
  }

  std::vector<float> input({1});
  auto in_tensor =
      predictor->GetInputTensor(predictor->GetInputNames().front());
  in_tensor->Reshape({1, 1});
  in_tensor->copy_from_cpu(input.data());

  predictor->ZeroCopyRun();

  auto out_tensor =
      predictor->GetOutputTensor(predictor->GetOutputNames().front());
  std::vector<float> data_o(10);
  out_tensor->copy_to_cpu(data_o.data());

  const std::vector<float> truth_values = {
      -0.00621776f, -0.00620937f, 0.00990623f,  -0.0039817f, -0.00074315f,
      0.61229795f,  -0.00491806f, -0.00068755f, 0.18409646f, 0.30090684f};
  const size_t expected_size = 1;
  EXPECT_EQ(predictor->GetOutputNames().size(), expected_size);
  for (size_t j = 0; j < truth_values.size(); ++j) {
    EXPECT_LT(std::abs(data_o[j] - truth_values[j]), 10e-6);
  }
  return 0;
}

#ifdef PADDLE_WITH_XPU
TEST(AnalysisPredictor, native_xpu) {
  AnalysisConfig config;
  config.EnableXpu();
  config.SetModel(FLAGS_infer_model + "/" + "mul_model");
  test_predictor(config);
  test_predictor_zero_copy(config);
}
#endif

#ifdef LITE_SUBGRAPH_WITH_XPU
TEST(AnalysisPredictor, lite_xpu) {
  AnalysisConfig config;
  config.EnableXpu();
  config.SetModel(FLAGS_infer_model + "/" + "mul_model");
  config.EnableLiteEngine(paddle::AnalysisConfig::Precision::kFloat32);
  test_predictor(config);
  test_predictor_zero_copy(config);
}
#endif

#if defined(PADDLE_WITH_CUDA) || defined(PADDLE_WITH_HIP)
TEST(AnalysisPredictor, thread_local_stream) {
  const size_t thread_num = 5;
  std::vector<std::thread> threads(thread_num);
  Barrier barrier(thread_num);
  for (size_t i = 0; i < threads.size(); ++i) {
    threads[i] = std::thread([&barrier, i]() {
      AnalysisConfig config;
      config.EnableUseGpu(100, 0);
      config.SetModel(FLAGS_infer_model + "/" + "mul_model");
      config.EnableGpuMultiStream();
      test_predictor(config, &barrier);
      test_predictor_zero_copy(config);
    });
  }
  for (auto& th : threads) {
    th.join();
  }
}

TEST(AnalysisPredictor, lite_engine) {
  AnalysisConfig config;
  config.EnableUseGpu(100, 0);
  config.SetModel(FLAGS_infer_model + "/" + "mul_model");
  config.EnableLiteEngine(paddle::AnalysisConfig::Precision::kFloat32);
  test_predictor(config);
  test_predictor_zero_copy(config);
}
#endif

}  // namespace inference
}  // namespace paddle
<|endoftext|>


<commit_before>#include "window.hh"

#include "assert.hh"
#include "highlighter_registry.hh"
#include "hooks_manager.hh"

#include <algorithm>
#include <sstream>

namespace Kakoune
{

BufferIterator Selection::begin() const
{
    return std::min(m_first, m_last);
}

BufferIterator Selection::end() const
{
    return std::max(m_first, m_last) + 1;
}

void Selection::merge_with(const Selection& selection)
{
    if (m_first <= m_last)
        m_first = std::min(m_first, selection.m_first);
    else
        m_first = std::max(m_first, selection.m_first);
    m_last = selection.m_last;
}

BufferString Selection::capture(size_t index) const
{
    if (index < m_captures.size())
        return m_captures[index];
    return "";
}

struct scoped_undo_group
{
    scoped_undo_group(Buffer& buffer)
        : m_buffer(buffer) { m_buffer.begin_undo_group(); }

    ~scoped_undo_group()   { m_buffer.end_undo_group(); }
private:
    Buffer& m_buffer;
};

Window::Window(Buffer& buffer)
    : m_buffer(buffer),
      m_position(0, 0),
      m_dimensions(0, 0),
      m_current_inserter(nullptr)
{
    m_selections.push_back(Selection(buffer.begin(), buffer.begin()));

    HighlighterRegistry& registry = HighlighterRegistry::instance();

    HooksManager::instance().run_hook("WinCreate", buffer.name(),
                                      Context(*this));

    registry.add_highlighter_to_window(*this, "expand_tabs", HighlighterParameters());
    registry.add_highlighter_to_window(*this, "highlight_selections", HighlighterParameters());
}

void Window::check_invariant() const
{
    assert(not m_selections.empty());
}

DisplayCoord Window::cursor_position() const
{
    check_invariant();
    return line_and_column_at(cursor_iterator());
}

BufferIterator Window::cursor_iterator() const
{
    check_invariant();
    return m_selections.back().last();
}

void Window::erase()
{
    scoped_undo_group undo_group(m_buffer);
    erase_noundo();
}

void Window::erase_noundo()
{
    check_invariant();
    for (auto& sel : m_selections)
        m_buffer.modify(Modification::make_erase(sel.begin(), sel.end()));
    scroll_to_keep_cursor_visible_ifn();
}

template<typename Iterator>
static DisplayCoord measure_string(Iterator begin, Iterator end)
{
    DisplayCoord result(0, 0);
    while (begin != end)
    {
        if (*begin == '\n')
        {
            ++result.line;
            result.column = 0;
        }
        else
            ++result.column;
        ++begin;
    }
    return result;
}

static DisplayCoord measure_string(const Window::String& string)
{
    return measure_string(string.begin(), string.end());
}

void Window::insert(const String& string)
{
    scoped_undo_group undo_group(m_buffer);
    insert_noundo(string);
}

void Window::insert_noundo(const String& string)
{
    for (auto& sel : m_selections)
        m_buffer.modify(Modification::make_insert(sel.begin(), string));
    scroll_to_keep_cursor_visible_ifn();
}

void Window::append(const String& string)
{
    scoped_undo_group undo_group(m_buffer);
    append_noundo(string);
}

void Window::append_noundo(const String& string)
{
    for (auto& sel : m_selections)
        m_buffer.modify(Modification::make_insert(sel.end(), string));
    scroll_to_keep_cursor_visible_ifn();
}

void Window::replace(const std::string& string)
{
    scoped_undo_group undo_group(m_buffer);
    erase_noundo();
    insert_noundo(string);
}

bool Window::undo()
{
    return m_buffer.undo();
}

bool Window::redo()
{
    return m_buffer.redo();
}

BufferIterator Window::iterator_at(const DisplayCoord& window_pos) const
{
    if (m_display_buffer.begin() == m_display_buffer.end())
        return m_buffer.begin();

    if (DisplayCoord(0,0) <= window_pos)
    {
        for (auto atom_it = m_display_buffer.begin();
             atom_it != m_display_buffer.end(); ++atom_it)
        {
            if (window_pos < atom_it->coord())
            {
                return (--atom_it)->iterator_at(window_pos);
            }
        }
    }

    return m_buffer.iterator_at(m_position + BufferCoord(window_pos));
}

DisplayCoord Window::line_and_column_at(const BufferIterator& iterator) const
{
    if (m_display_buffer.begin() == m_display_buffer.end())
        return DisplayCoord(0, 0);

    if (iterator >= m_display_buffer.front().begin() and
        iterator <  m_display_buffer.back().end())
    {
        for (auto& atom : m_display_buffer)
        {
            if (atom.end() > iterator)
            {
                assert(atom.begin() <= iterator);
                return atom.line_and_column_at(iterator);
            }
        }
    }
    BufferCoord coord = m_buffer.line_and_column_at(iterator);
    return DisplayCoord(coord.line - m_position.line,
                        coord.column - m_position.column);
}

void Window::clear_selections()
{
    check_invariant();
    BufferIterator pos = m_selections.back().last();

    if (*pos == '\n' and not pos.is_begin() and *(pos-1) != '\n')
        --pos;

    Selection sel = Selection(pos, pos);
    m_selections.clear();
    m_selections.push_back(std::move(sel));
}

void Window::select(const Selector& selector, bool append)
{
    check_invariant();

    if (not append)
    {
        Selection sel = selector(m_selections.back().last());
        m_selections.clear();
        m_selections.push_back(std::move(sel));
    }
    else
    {
        for (auto& sel : m_selections)
        {
            sel.merge_with(selector(sel.last()));
        }
    }
    scroll_to_keep_cursor_visible_ifn();
}

void Window::multi_select(const MultiSelector& selector)
{
    check_invariant();

    SelectionList new_selections;
    for (auto& sel : m_selections)
    {
        SelectionList selections = selector(sel);
        std::copy(selections.begin(), selections.end(),
                  std::back_inserter(new_selections));
    }
    if (not new_selections.empty())
    {
        m_selections = std::move(new_selections);
        scroll_to_keep_cursor_visible_ifn();
    }
}

BufferString Window::selection_content() const
{
    check_invariant();

    return m_buffer.string(m_selections.back().begin(),
                           m_selections.back().end());
}

void Window::move_cursor(const DisplayCoord& offset, bool append)
{
    if (not append)
    {
        BufferCoord pos = m_buffer.line_and_column_at(cursor_iterator());
        move_cursor_to(m_buffer.iterator_at(pos + BufferCoord(offset)));
    }
    else
    {
        for (auto& sel : m_selections)
        {
            BufferCoord pos = m_buffer.line_and_column_at(sel.last());
            sel = Selection(sel.first(), m_buffer.iterator_at(pos + BufferCoord(offset)));
        }
        scroll_to_keep_cursor_visible_ifn();
    }
}

void Window::move_cursor_to(const BufferIterator& iterator)
{
    m_selections.clear();
    m_selections.push_back(Selection(iterator, iterator));

    scroll_to_keep_cursor_visible_ifn();
}

void Window::update_display_buffer()
{
    m_display_buffer.clear();

    BufferIterator begin = m_buffer.iterator_at(m_position);
    BufferIterator end = m_buffer.iterator_at(m_position +
                                              BufferCoord(m_dimensions.line, m_dimensions.column))+1;
    if (begin == end)
        return;

    m_display_buffer.append(DisplayAtom(DisplayCoord(0,0), begin, end));

    for (auto& highlighter : m_highlighters)
    {
        highlighter.second(m_display_buffer);
        m_display_buffer.check_invariant();
    }
}

void Window::set_dimensions(const DisplayCoord& dimensions)
{
    m_dimensions = dimensions;
}

void Window::scroll_to_keep_cursor_visible_ifn()
{
    check_invariant();

    DisplayCoord cursor = line_and_column_at(m_selections.back().last());
    if (cursor.line < 0)
    {
        m_position.line = std::max(m_position.line + cursor.line, 0);
    }
    else if (cursor.line >= m_dimensions.line)
    {
        m_position.line += cursor.line - (m_dimensions.line - 1);
    }

    if (cursor.column < 0)
    {
        m_position.column = std::max(m_position.column + cursor.column, 0);
    }
    else if (cursor.column >= m_dimensions.column)
    {
        m_position.column += cursor.column - (m_dimensions.column - 1);
    }
}

std::string Window::status_line() const
{
    BufferCoord cursor = m_buffer.line_and_column_at(m_selections.back().last());
    std::ostringstream oss;
    oss << m_buffer.name();
    if (m_buffer.is_modified())
        oss << " [+]";
    oss << " -- " << cursor.line+1 << "," << cursor.column+1
        << " -- " << m_selections.size() << " sel -- ";
    if (m_current_inserter)
        oss << "[Insert]";
    return oss.str();
}

void Window::add_highlighter(HighlighterAndId&& highlighter)
{
    if (m_highlighters.contains(highlighter.first))
        throw id_not_unique(highlighter.first);
    m_highlighters.append(std::forward<HighlighterAndId>(highlighter));
}

void Window::remove_highlighter(const std::string& id)
{
    m_highlighters.remove(id);
}

CandidateList Window::complete_highlighterid(const std::string& prefix,
                                             size_t cursor_pos)
{
    return m_highlighters.complete_id<str_to_str>(prefix, cursor_pos);
}

void Window::add_filter(FilterAndId&& filter)
{
    if (m_filters.contains(filter.first))
        throw id_not_unique(filter.first);
    m_filters.append(std::forward<FilterAndId>(filter));
}

void Window::remove_filter(const std::string& id)
{
    m_filters.remove(id);
}

CandidateList Window::complete_filterid(const std::string& prefix,
                                        size_t cursor_pos)
{
    return m_filters.complete_id<str_to_str>(prefix, cursor_pos);
}

IncrementalInserter::IncrementalInserter(Window& window, Mode mode)
    : m_window(window)
{
    assert(not m_window.m_current_inserter);
    m_window.m_current_inserter = this;
    m_window.check_invariant();

    m_window.m_buffer.begin_undo_group();

    if (mode == Mode::Change)
        window.erase_noundo();

    for (auto& sel : m_window.m_selections)
    {
        DynamicBufferIterator pos;
        switch (mode)
        {
        case Mode::Insert: pos = sel.begin(); break;
        case Mode::Append: pos = sel.end(); break;
        case Mode::Change: pos = sel.begin(); break;

        case Mode::OpenLineBelow:
        case Mode::AppendAtLineEnd:
            pos = m_window.m_buffer.iterator_at_line_end(sel.end() - 1) - 1;
            if (mode == Mode::OpenLineBelow)
                apply(Modification::make_insert(pos, "\n"));
            break;

        case Mode::OpenLineAbove:
        case Mode::InsertAtLineBegin:
            pos = m_window.m_buffer.iterator_at_line_begin(sel.begin());
            if (mode == Mode::OpenLineAbove)
                apply(Modification::make_insert(--pos, "\n"));
            break;
        }
        sel = Selection(pos, pos, sel.captures());
    }
}

IncrementalInserter::~IncrementalInserter()
{
    move_cursor(DisplayCoord(0, -1));
    assert(m_window.m_current_inserter == this);
    m_window.m_current_inserter = nullptr;

    m_window.m_buffer.end_undo_group();
}

void IncrementalInserter::apply(Modification&& modification) const
{
    for (auto filter : m_window.m_filters)
        filter.second(m_window.buffer(), modification);
    m_window.buffer().modify(std::move(modification));
}

void IncrementalInserter::insert(const Window::String& string)
{
    for (auto& sel : m_window.m_selections)
        apply(Modification::make_insert(sel.begin(), string));
}

void IncrementalInserter::insert_capture(size_t index)
{
    for (auto& sel : m_window.m_selections)
        m_window.m_buffer.modify(Modification::make_insert(sel.begin(),
                                                           sel.capture(index)));
    m_window.scroll_to_keep_cursor_visible_ifn();
}

void IncrementalInserter::erase()
{
    for (auto& sel : m_window.m_selections)
    {
        sel = Selection(sel.first() - 1, sel.last() - 1);
        apply(Modification::make_erase(sel.begin(), sel.end()));
    }

    m_window.scroll_to_keep_cursor_visible_ifn();
}

void IncrementalInserter::move_cursor(const DisplayCoord& offset)
{
    for (auto& sel : m_window.m_selections)
    {
        DisplayCoord pos = m_window.line_and_column_at(sel.last());
        BufferIterator it = m_window.iterator_at(pos + offset);
        sel = Selection(it, it);
    }
}

}
<commit_msg>Window: throw when multiselect results in no selections<commit_after>#include "window.hh"

#include "assert.hh"
#include "highlighter_registry.hh"
#include "hooks_manager.hh"

#include <algorithm>
#include <sstream>

namespace Kakoune
{

BufferIterator Selection::begin() const
{
    return std::min(m_first, m_last);
}

BufferIterator Selection::end() const
{
    return std::max(m_first, m_last) + 1;
}

void Selection::merge_with(const Selection& selection)
{
    if (m_first <= m_last)
        m_first = std::min(m_first, selection.m_first);
    else
        m_first = std::max(m_first, selection.m_first);
    m_last = selection.m_last;
}

BufferString Selection::capture(size_t index) const
{
    if (index < m_captures.size())
        return m_captures[index];
    return "";
}

struct scoped_undo_group
{
    scoped_undo_group(Buffer& buffer)
        : m_buffer(buffer) { m_buffer.begin_undo_group(); }

    ~scoped_undo_group()   { m_buffer.end_undo_group(); }
private:
    Buffer& m_buffer;
};

Window::Window(Buffer& buffer)
    : m_buffer(buffer),
      m_position(0, 0),
      m_dimensions(0, 0),
      m_current_inserter(nullptr)
{
    m_selections.push_back(Selection(buffer.begin(), buffer.begin()));

    HighlighterRegistry& registry = HighlighterRegistry::instance();

    HooksManager::instance().run_hook("WinCreate", buffer.name(),
                                      Context(*this));

    registry.add_highlighter_to_window(*this, "expand_tabs", HighlighterParameters());
    registry.add_highlighter_to_window(*this, "highlight_selections", HighlighterParameters());
}

void Window::check_invariant() const
{
    assert(not m_selections.empty());
}

DisplayCoord Window::cursor_position() const
{
    check_invariant();
    return line_and_column_at(cursor_iterator());
}

BufferIterator Window::cursor_iterator() const
{
    check_invariant();
    return m_selections.back().last();
}

void Window::erase()
{
    scoped_undo_group undo_group(m_buffer);
    erase_noundo();
}

void Window::erase_noundo()
{
    check_invariant();
    for (auto& sel : m_selections)
        m_buffer.modify(Modification::make_erase(sel.begin(), sel.end()));
    scroll_to_keep_cursor_visible_ifn();
}

template<typename Iterator>
static DisplayCoord measure_string(Iterator begin, Iterator end)
{
    DisplayCoord result(0, 0);
    while (begin != end)
    {
        if (*begin == '\n')
        {
            ++result.line;
            result.column = 0;
        }
        else
            ++result.column;
        ++begin;
    }
    return result;
}

static DisplayCoord measure_string(const Window::String& string)
{
    return measure_string(string.begin(), string.end());
}

void Window::insert(const String& string)
{
    scoped_undo_group undo_group(m_buffer);
    insert_noundo(string);
}

void Window::insert_noundo(const String& string)
{
    for (auto& sel : m_selections)
        m_buffer.modify(Modification::make_insert(sel.begin(), string));
    scroll_to_keep_cursor_visible_ifn();
}

void Window::append(const String& string)
{
    scoped_undo_group undo_group(m_buffer);
    append_noundo(string);
}

void Window::append_noundo(const String& string)
{
    for (auto& sel : m_selections)
        m_buffer.modify(Modification::make_insert(sel.end(), string));
    scroll_to_keep_cursor_visible_ifn();
}

void Window::replace(const std::string& string)
{
    scoped_undo_group undo_group(m_buffer);
    erase_noundo();
    insert_noundo(string);
}

bool Window::undo()
{
    return m_buffer.undo();
}

bool Window::redo()
{
    return m_buffer.redo();
}

BufferIterator Window::iterator_at(const DisplayCoord& window_pos) const
{
    if (m_display_buffer.begin() == m_display_buffer.end())
        return m_buffer.begin();

    if (DisplayCoord(0,0) <= window_pos)
    {
        for (auto atom_it = m_display_buffer.begin();
             atom_it != m_display_buffer.end(); ++atom_it)
        {
            if (window_pos < atom_it->coord())
            {
                return (--atom_it)->iterator_at(window_pos);
            }
        }
    }

    return m_buffer.iterator_at(m_position + BufferCoord(window_pos));
}

DisplayCoord Window::line_and_column_at(const BufferIterator& iterator) const
{
    if (m_display_buffer.begin() == m_display_buffer.end())
        return DisplayCoord(0, 0);

    if (iterator >= m_display_buffer.front().begin() and
        iterator <  m_display_buffer.back().end())
    {
        for (auto& atom : m_display_buffer)
        {
            if (atom.end() > iterator)
            {
                assert(atom.begin() <= iterator);
                return atom.line_and_column_at(iterator);
            }
        }
    }
    BufferCoord coord = m_buffer.line_and_column_at(iterator);
    return DisplayCoord(coord.line - m_position.line,
                        coord.column - m_position.column);
}

void Window::clear_selections()
{
    check_invariant();
    BufferIterator pos = m_selections.back().last();

    if (*pos == '\n' and not pos.is_begin() and *(pos-1) != '\n')
        --pos;

    Selection sel = Selection(pos, pos);
    m_selections.clear();
    m_selections.push_back(std::move(sel));
}

void Window::select(const Selector& selector, bool append)
{
    check_invariant();

    if (not append)
    {
        Selection sel = selector(m_selections.back().last());
        m_selections.clear();
        m_selections.push_back(std::move(sel));
    }
    else
    {
        for (auto& sel : m_selections)
        {
            sel.merge_with(selector(sel.last()));
        }
    }
    scroll_to_keep_cursor_visible_ifn();
}

struct nothing_selected : public runtime_error
{
    nothing_selected() : runtime_error("nothing was selected") {}
};

void Window::multi_select(const MultiSelector& selector)
{
    check_invariant();

    SelectionList new_selections;
    for (auto& sel : m_selections)
    {
        SelectionList selections = selector(sel);
        std::copy(selections.begin(), selections.end(),
                  std::back_inserter(new_selections));
    }
    if (new_selections.empty())
        throw nothing_selected();

    m_selections = std::move(new_selections);
    scroll_to_keep_cursor_visible_ifn();
}

BufferString Window::selection_content() const
{
    check_invariant();

    return m_buffer.string(m_selections.back().begin(),
                           m_selections.back().end());
}

void Window::move_cursor(const DisplayCoord& offset, bool append)
{
    if (not append)
    {
        BufferCoord pos = m_buffer.line_and_column_at(cursor_iterator());
        move_cursor_to(m_buffer.iterator_at(pos + BufferCoord(offset)));
    }
    else
    {
        for (auto& sel : m_selections)
        {
            BufferCoord pos = m_buffer.line_and_column_at(sel.last());
            sel = Selection(sel.first(), m_buffer.iterator_at(pos + BufferCoord(offset)));
        }
        scroll_to_keep_cursor_visible_ifn();
    }
}

void Window::move_cursor_to(const BufferIterator& iterator)
{
    m_selections.clear();
    m_selections.push_back(Selection(iterator, iterator));

    scroll_to_keep_cursor_visible_ifn();
}

void Window::update_display_buffer()
{
    m_display_buffer.clear();

    BufferIterator begin = m_buffer.iterator_at(m_position);
    BufferIterator end = m_buffer.iterator_at(m_position +
                                              BufferCoord(m_dimensions.line, m_dimensions.column))+1;
    if (begin == end)
        return;

    m_display_buffer.append(DisplayAtom(DisplayCoord(0,0), begin, end));

    for (auto& highlighter : m_highlighters)
    {
        highlighter.second(m_display_buffer);
        m_display_buffer.check_invariant();
    }
}

void Window::set_dimensions(const DisplayCoord& dimensions)
{
    m_dimensions = dimensions;
}

void Window::scroll_to_keep_cursor_visible_ifn()
{
    check_invariant();

    DisplayCoord cursor = line_and_column_at(m_selections.back().last());
    if (cursor.line < 0)
    {
        m_position.line = std::max(m_position.line + cursor.line, 0);
    }
    else if (cursor.line >= m_dimensions.line)
    {
        m_position.line += cursor.line - (m_dimensions.line - 1);
    }

    if (cursor.column < 0)
    {
        m_position.column = std::max(m_position.column + cursor.column, 0);
    }
    else if (cursor.column >= m_dimensions.column)
    {
        m_position.column += cursor.column - (m_dimensions.column - 1);
    }
}

std::string Window::status_line() const
{
    BufferCoord cursor = m_buffer.line_and_column_at(m_selections.back().last());
    std::ostringstream oss;
    oss << m_buffer.name();
    if (m_buffer.is_modified())
        oss << " [+]";
    oss << " -- " << cursor.line+1 << "," << cursor.column+1
        << " -- " << m_selections.size() << " sel -- ";
    if (m_current_inserter)
        oss << "[Insert]";
    return oss.str();
}

void Window::add_highlighter(HighlighterAndId&& highlighter)
{
    if (m_highlighters.contains(highlighter.first))
        throw id_not_unique(highlighter.first);
    m_highlighters.append(std::forward<HighlighterAndId>(highlighter));
}

void Window::remove_highlighter(const std::string& id)
{
    m_highlighters.remove(id);
}

CandidateList Window::complete_highlighterid(const std::string& prefix,
                                             size_t cursor_pos)
{
    return m_highlighters.complete_id<str_to_str>(prefix, cursor_pos);
}

void Window::add_filter(FilterAndId&& filter)
{
    if (m_filters.contains(filter.first))
        throw id_not_unique(filter.first);
    m_filters.append(std::forward<FilterAndId>(filter));
}

void Window::remove_filter(const std::string& id)
{
    m_filters.remove(id);
}

CandidateList Window::complete_filterid(const std::string& prefix,
                                        size_t cursor_pos)
{
    return m_filters.complete_id<str_to_str>(prefix, cursor_pos);
}

IncrementalInserter::IncrementalInserter(Window& window, Mode mode)
    : m_window(window)
{
    assert(not m_window.m_current_inserter);
    m_window.m_current_inserter = this;
    m_window.check_invariant();

    m_window.m_buffer.begin_undo_group();

    if (mode == Mode::Change)
        window.erase_noundo();

    for (auto& sel : m_window.m_selections)
    {
        DynamicBufferIterator pos;
        switch (mode)
        {
        case Mode::Insert: pos = sel.begin(); break;
        case Mode::Append: pos = sel.end(); break;
        case Mode::Change: pos = sel.begin(); break;

        case Mode::OpenLineBelow:
        case Mode::AppendAtLineEnd:
            pos = m_window.m_buffer.iterator_at_line_end(sel.end() - 1) - 1;
            if (mode == Mode::OpenLineBelow)
                apply(Modification::make_insert(pos, "\n"));
            break;

        case Mode::OpenLineAbove:
        case Mode::InsertAtLineBegin:
            pos = m_window.m_buffer.iterator_at_line_begin(sel.begin());
            if (mode == Mode::OpenLineAbove)
                apply(Modification::make_insert(--pos, "\n"));
            break;
        }
        sel = Selection(pos, pos, sel.captures());
    }
}

IncrementalInserter::~IncrementalInserter()
{
    move_cursor(DisplayCoord(0, -1));
    assert(m_window.m_current_inserter == this);
    m_window.m_current_inserter = nullptr;

    m_window.m_buffer.end_undo_group();
}

void IncrementalInserter::apply(Modification&& modification) const
{
    for (auto filter : m_window.m_filters)
        filter.second(m_window.buffer(), modification);
    m_window.buffer().modify(std::move(modification));
}

void IncrementalInserter::insert(const Window::String& string)
{
    for (auto& sel : m_window.m_selections)
        apply(Modification::make_insert(sel.begin(), string));
}

void IncrementalInserter::insert_capture(size_t index)
{
    for (auto& sel : m_window.m_selections)
        m_window.m_buffer.modify(Modification::make_insert(sel.begin(),
                                                           sel.capture(index)));
    m_window.scroll_to_keep_cursor_visible_ifn();
}

void IncrementalInserter::erase()
{
    for (auto& sel : m_window.m_selections)
    {
        sel = Selection(sel.first() - 1, sel.last() - 1);
        apply(Modification::make_erase(sel.begin(), sel.end()));
    }

    m_window.scroll_to_keep_cursor_visible_ifn();
}

void IncrementalInserter::move_cursor(const DisplayCoord& offset)
{
    for (auto& sel : m_window.m_selections)
    {
        DisplayCoord pos = m_window.line_and_column_at(sel.last());
        BufferIterator it = m_window.iterator_at(pos + offset);
        sel = Selection(it, it);
    }
}

}
<|endoftext|>


<commit_before>#include "format_twobit.h"

// Fixme: Here for debugging
#define MAX_ALLOC 524288

enum {
	ACTION_DUMP,
	ACTION_INFO,
	ACTION_SHOW
};

int FormatTwoBit::dump(FILE *fp) {
	return helper(fp, ACTION_DUMP, 0);
}

int FormatTwoBit::info(FILE *fp, int verbose) {
	return helper(fp, ACTION_INFO, verbose);
}

int FormatTwoBit::show(FILE *fp) {
	return helper(fp, ACTION_SHOW, 0);
}

int FormatTwoBit::helper(FILE *fp, int action, int verbose) {
	char buf[256];

	// Fixme: Read header size only
	int n = fread(buf,1,sizeof(_2bit_header_t),fp);

	_2bit_header_t *header = (_2bit_header_t*)buf;

	if (
		(header->signature != 0x1a412743) &&
		(header->signature != 0x4327411a)
	) {
		printf("2bit: Error, not a 2bit file\n");
		return -1;
	}

	// Determine endian format.
	int endian_is_native = (*(uint32_t*)buf == 0x1a412743) ? 1 : 0;
	// Fixme, we care about big/little not native or swapped
	// Use htonl

	if (verbose >= 1) {
		printf("File format:    2bit\n");
		printf("Endian:         %s\n", endian_is_native ? "native" : "swapped");
		printf("Version:        %d\n", header->version); // Fixme, endians
		printf("Sequence Count: %d\n", header->sequenceCount); // Fixme, endians
		printf("Reserved:       %d\n", header->reserved); // Fixme, endians
		if (verbose == 1)
			return 0;
	}

	_2bit_index_t *index = (_2bit_index_t*)malloc(sizeof(_2bit_index_t)*header->sequenceCount);
	if (!index) {
		fprintf(stderr, "Error: Not enough memory to allocate %d index tables\n", header->sequenceCount);
		return -1;
	}

	for (unsigned i = 0; i < header->sequenceCount; i++) {
		_2bit_seq_hdr_t *seq_hdr = &index[i].seq_hdr;
		// Fixme: Excessive read calls
		n = fread(&seq_hdr->nameSize,1,1,fp);
		n = fread(&seq_hdr->name,1,seq_hdr->nameSize,fp);
		n = fread(&seq_hdr->offset,1,sizeof(uint32_t),fp);
		seq_hdr->name[seq_hdr->nameSize] = 0;
		// printf("Sequence #%d, \"%s\"\n", i, seq_hdr.name);
	}

	for (unsigned i = 0; i < header->sequenceCount; i++) {
		// Fixme: Excessive read calls
		n = fread(&index[i].dnaSize,    sizeof(uint32_t),1,fp);
		n = fread(&index[i].nBlockCount,sizeof(uint32_t),1,fp);
		if (index[i].nBlockCount) {
			if (index[i].nBlockCount > MAX_ALLOC)
				index[i].nBlockCount = MAX_ALLOC;

			index[i].nBlockStarts = (uint32_t*)malloc(sizeof(uint32_t)*index[i].nBlockCount);
			if (!index[i].nBlockStarts) {
				// Fixme: Convert to class to we can auto free.
				printf("Error, unable to allocate %d bytes.\n", sizeof(uint32_t)*index[i].nBlockCount);
				return -1;
			}

			index[i].nBlockSizes  = (uint32_t*)malloc(sizeof(uint32_t)*index[i].nBlockCount);
			if (!index[i].nBlockSizes) {
				// Fixme: Convert to class to we can auto free.
				printf("Error, unable to allocate %d bytes.\n", sizeof(uint32_t)*index[i].nBlockCount);
				return -1;
			}

			fread(index[i].nBlockStarts, sizeof(uint32_t), index[i].nBlockCount, fp);
			fread(index[i].nBlockSizes,  sizeof(uint32_t), index[i].nBlockCount, fp);

		} else {
			index[i].nBlockStarts =
			index[i].nBlockSizes = 0;
		}

		// Todo: Verify the blocks are in order
		// Related, how are these used?

		n = fread(&index[i].maskBlockCount,sizeof(uint32_t),1,fp);
		if (verbose >= 2) {
			printf(
				"Seq #%3d: %6d kbase, blocks %3d, masks %6d, \"%s\" \n",
				i,
				index[i].dnaSize / 1000,
				index[i].nBlockCount, index[i].maskBlockCount,
				index[i].seq_hdr.name
			);
		}

		if (verbose >= 3) {
			for (unsigned o = 0; o < index[i].nBlockCount; o++) {
				printf("   Block #%d: start: %d, size: %d\n",
					o, index[i].nBlockStarts[o], index[i].nBlockSizes[o]
				);
			}
		}

		if (!index[i].maskBlockCount) {
			index[i].maskBlockStarts = NULL;
			index[i].maskBlockSizes = NULL;
		} else {
			if (index[i].maskBlockCount > MAX_ALLOC)
				index[i].maskBlockCount = MAX_ALLOC;

			index[i].maskBlockStarts = (uint32_t*)malloc(sizeof(uint32_t)*index[i].maskBlockCount);
			index[i].maskBlockSizes  = (uint32_t*)malloc(sizeof(uint32_t)*index[i].maskBlockCount);

			n = fread(index[i].maskBlockStarts, sizeof(uint32_t), index[i].maskBlockCount, fp);
			if ((unsigned)n != index[i].maskBlockCount) {
				printf("Error: Unable to read mask block starts at index %d, short file?\n", i);
				return -1;
			}

			n = fread(index[i].maskBlockSizes,  sizeof(uint32_t), index[i].maskBlockCount, fp);
			if ((unsigned)n != index[i].maskBlockCount) {
				printf("Error: Unable to read mask block count at index %d, short file?\n", i);
				return -1;
			}

			if (verbose >= 3) {
				for (unsigned o = 0; o < index[i].maskBlockCount; o++) {
					printf("   Mask #%d: start: %d, size: %d\n",
						o, index[i].maskBlockStarts[o], index[i].maskBlockSizes[o]
					);
				}
			}

			// Todo: Walk the list of masks to ensure they are saved in alphabetical order
		}

		// Reserved
		n = fread(&index[i].reserved,sizeof(uint32_t),1,fp);

		/** Fixme: In some cases, we probably actually want to load this data. */
		index[i].packedDna_offset = ftell(fp);
		if (action == ACTION_INFO)
			fseek(fp,(index[i].dnaSize+3)/4,SEEK_CUR);
		else {
			unsigned cur_block_i = 0;      // Note: Requires the block list to be in order
			unsigned cur_mask_i = 0;       // Note: Requires the mask list to be in order
			unsigned cur_bp_pos = 0;       // Current base pair position.
			unsigned cur_print_width = 60; // Number of base pairs to print per line (for future show command)
			char buf[8192];
			int bpc = index[i].dnaSize;
			int len = (index[i].dnaSize+3)/4;
			while (len > 0) {
				int toread = len > sizeof(buf) ? sizeof(buf) : len;
				int available = index[i].dnaSize;
				// printf("ToRead :%d\n", toread);
				n = fread(&buf[0], 1, toread, fp);
				if (toread != n) {
					printf("Error: Unable to read DNA data\n");
					return -1;
				}
				for (unsigned print_pos = 0; print_pos < toread; print_pos++) {
					const char c[4] = { 'T', 'C', 'A', 'G' };
					char ch = buf[print_pos];
					for (unsigned o = 0; o < 4; o++) {
						if (available) {
							if (action == ACTION_SHOW)
								if (cur_bp_pos % cur_print_width == 0)
									printf("\n%9d: ", cur_bp_pos);
							// Fixme: Check blocks and masks as appropriate. And don't go over the end
						test_again:
							if (cur_block_i < index[i].nBlockCount) {
								if (cur_bp_pos >= index[i].nBlockStarts[cur_block_i]) {
									if (cur_bp_pos > index[i].nBlockStarts[cur_block_i] + index[i].nBlockSizes[cur_block_i]) {
										cur_block_i++;
										goto test_again;
									}
									printf("N");
								} else {
									printf("%c", c[(ch >> 6) & 3]);
								}
							} else {
								printf("%c", c[(ch >> 6) & 3]);
							}
							ch <<= 2;
							available--;
							cur_bp_pos++;
						}
					}
				}
				len -= n;
			}
		}
	}

	// EOF Sanity Check
	if (1) {
		char buf[8192];
		n = fread(buf,1,sizeof(buf),fp);
		if (n != 0)
			printf("Warning: Additional data past where the end of file should be.\n");
	}

	return 0;
}
<commit_msg>Since we are mostly in base10 for the output, switch the default display width to 50.<commit_after>#include "format_twobit.h"

// Fixme: Here for debugging
#define MAX_ALLOC 524288

enum {
	ACTION_DUMP,
	ACTION_INFO,
	ACTION_SHOW
};

int FormatTwoBit::dump(FILE *fp) {
	return helper(fp, ACTION_DUMP, 0);
}

int FormatTwoBit::info(FILE *fp, int verbose) {
	return helper(fp, ACTION_INFO, verbose);
}

int FormatTwoBit::show(FILE *fp) {
	return helper(fp, ACTION_SHOW, 0);
}

int FormatTwoBit::helper(FILE *fp, int action, int verbose) {
	char buf[256];

	// Fixme: Read header size only
	int n = fread(buf,1,sizeof(_2bit_header_t),fp);

	_2bit_header_t *header = (_2bit_header_t*)buf;

	if (
		(header->signature != 0x1a412743) &&
		(header->signature != 0x4327411a)
	) {
		printf("2bit: Error, not a 2bit file\n");
		return -1;
	}

	// Determine endian format.
	int endian_is_native = (*(uint32_t*)buf == 0x1a412743) ? 1 : 0;
	// Fixme, we care about big/little not native or swapped
	// Use htonl

	if (verbose >= 1) {
		printf("File format:    2bit\n");
		printf("Endian:         %s\n", endian_is_native ? "native" : "swapped");
		printf("Version:        %d\n", header->version); // Fixme, endians
		printf("Sequence Count: %d\n", header->sequenceCount); // Fixme, endians
		printf("Reserved:       %d\n", header->reserved); // Fixme, endians
		if (verbose == 1)
			return 0;
	}

	_2bit_index_t *index = (_2bit_index_t*)malloc(sizeof(_2bit_index_t)*header->sequenceCount);
	if (!index) {
		fprintf(stderr, "Error: Not enough memory to allocate %d index tables\n", header->sequenceCount);
		return -1;
	}

	for (unsigned i = 0; i < header->sequenceCount; i++) {
		_2bit_seq_hdr_t *seq_hdr = &index[i].seq_hdr;
		// Fixme: Excessive read calls
		n = fread(&seq_hdr->nameSize,1,1,fp);
		n = fread(&seq_hdr->name,1,seq_hdr->nameSize,fp);
		n = fread(&seq_hdr->offset,1,sizeof(uint32_t),fp);
		seq_hdr->name[seq_hdr->nameSize] = 0;
		// printf("Sequence #%d, \"%s\"\n", i, seq_hdr.name);
	}

	for (unsigned i = 0; i < header->sequenceCount; i++) {
		// Fixme: Excessive read calls
		n = fread(&index[i].dnaSize,    sizeof(uint32_t),1,fp);
		n = fread(&index[i].nBlockCount,sizeof(uint32_t),1,fp);
		if (index[i].nBlockCount) {
			if (index[i].nBlockCount > MAX_ALLOC)
				index[i].nBlockCount = MAX_ALLOC;

			index[i].nBlockStarts = (uint32_t*)malloc(sizeof(uint32_t)*index[i].nBlockCount);
			if (!index[i].nBlockStarts) {
				// Fixme: Convert to class to we can auto free.
				printf("Error, unable to allocate %d bytes.\n", sizeof(uint32_t)*index[i].nBlockCount);
				return -1;
			}

			index[i].nBlockSizes  = (uint32_t*)malloc(sizeof(uint32_t)*index[i].nBlockCount);
			if (!index[i].nBlockSizes) {
				// Fixme: Convert to class to we can auto free.
				printf("Error, unable to allocate %d bytes.\n", sizeof(uint32_t)*index[i].nBlockCount);
				return -1;
			}

			fread(index[i].nBlockStarts, sizeof(uint32_t), index[i].nBlockCount, fp);
			fread(index[i].nBlockSizes,  sizeof(uint32_t), index[i].nBlockCount, fp);

		} else {
			index[i].nBlockStarts =
			index[i].nBlockSizes = 0;
		}

		// Todo: Verify the blocks are in order
		// Related, how are these used?

		n = fread(&index[i].maskBlockCount,sizeof(uint32_t),1,fp);
		if (verbose >= 2) {
			printf(
				"Seq #%3d: %6d kbase, blocks %3d, masks %6d, \"%s\" \n",
				i,
				index[i].dnaSize / 1000,
				index[i].nBlockCount, index[i].maskBlockCount,
				index[i].seq_hdr.name
			);
		}

		if (verbose >= 3) {
			for (unsigned o = 0; o < index[i].nBlockCount; o++) {
				printf("   Block #%d: start: %d, size: %d\n",
					o, index[i].nBlockStarts[o], index[i].nBlockSizes[o]
				);
			}
		}

		if (!index[i].maskBlockCount) {
			index[i].maskBlockStarts = NULL;
			index[i].maskBlockSizes = NULL;
		} else {
			if (index[i].maskBlockCount > MAX_ALLOC)
				index[i].maskBlockCount = MAX_ALLOC;

			index[i].maskBlockStarts = (uint32_t*)malloc(sizeof(uint32_t)*index[i].maskBlockCount);
			index[i].maskBlockSizes  = (uint32_t*)malloc(sizeof(uint32_t)*index[i].maskBlockCount);

			n = fread(index[i].maskBlockStarts, sizeof(uint32_t), index[i].maskBlockCount, fp);
			if ((unsigned)n != index[i].maskBlockCount) {
				printf("Error: Unable to read mask block starts at index %d, short file?\n", i);
				return -1;
			}

			n = fread(index[i].maskBlockSizes,  sizeof(uint32_t), index[i].maskBlockCount, fp);
			if ((unsigned)n != index[i].maskBlockCount) {
				printf("Error: Unable to read mask block count at index %d, short file?\n", i);
				return -1;
			}

			if (verbose >= 3) {
				for (unsigned o = 0; o < index[i].maskBlockCount; o++) {
					printf("   Mask #%d: start: %d, size: %d\n",
						o, index[i].maskBlockStarts[o], index[i].maskBlockSizes[o]
					);
				}
			}

			// Todo: Walk the list of masks to ensure they are saved in alphabetical order
		}

		// Reserved
		n = fread(&index[i].reserved,sizeof(uint32_t),1,fp);

		/** Fixme: In some cases, we probably actually want to load this data. */
		index[i].packedDna_offset = ftell(fp);
		if (action == ACTION_INFO)
			fseek(fp,(index[i].dnaSize+3)/4,SEEK_CUR);
		else {
			unsigned cur_block_i = 0;      // Note: Requires the block list to be in order
			unsigned cur_mask_i = 0;       // Note: Requires the mask list to be in order
			unsigned cur_bp_pos = 0;       // Current base pair position.
			unsigned cur_print_width = 50; // Number of base pairs to print per line (for future show command)
			char buf[8192];
			int bpc = index[i].dnaSize;
			int len = (index[i].dnaSize+3)/4;
			while (len > 0) {
				int toread = len > sizeof(buf) ? sizeof(buf) : len;
				int available = index[i].dnaSize;
				// printf("ToRead :%d\n", toread);
				n = fread(&buf[0], 1, toread, fp);
				if (toread != n) {
					printf("Error: Unable to read DNA data\n");
					return -1;
				}
				for (unsigned print_pos = 0; print_pos < toread; print_pos++) {
					const char c[4] = { 'T', 'C', 'A', 'G' };
					char ch = buf[print_pos];
					for (unsigned o = 0; o < 4; o++) {
						if (available) {
							if (action == ACTION_SHOW)
								if (cur_bp_pos % cur_print_width == 0)
									printf("\n%9d: ", cur_bp_pos);
							// Fixme: Check blocks and masks as appropriate. And don't go over the end
						test_again:
							if (cur_block_i < index[i].nBlockCount) {
								if (cur_bp_pos >= index[i].nBlockStarts[cur_block_i]) {
									if (cur_bp_pos > index[i].nBlockStarts[cur_block_i] + index[i].nBlockSizes[cur_block_i]) {
										cur_block_i++;
										goto test_again;
									}
									printf("N");
								} else {
									printf("%c", c[(ch >> 6) & 3]);
								}
							} else {
								printf("%c", c[(ch >> 6) & 3]);
							}
							ch <<= 2;
							available--;
							cur_bp_pos++;
						}
					}
				}
				len -= n;
			}
		}
	}

	// EOF Sanity Check
	if (1) {
		char buf[8192];
		n = fread(buf,1,sizeof(buf),fp);
		if (n != 0)
			printf("Warning: Additional data past where the end of file should be.\n");
	}

	return 0;
}
<|endoftext|>


<commit_before>//===----------------------------------------------------------------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is dual licensed under the MIT and the University of Illinois Open
// Source Licenses. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

// <cmath>

// isinf

// XFAIL: linux

#include <cmath>
#include <type_traits>
#include <cassert>

int main()
{
#ifdef isnan
#error isnan defined
#endif
    static_assert((std::is_same<decltype(std::isnan((float)0)), bool>::value), "");
    static_assert((std::is_same<decltype(std::isnan((double)0)), bool>::value), "");
    static_assert((std::is_same<decltype(std::isnan(0)), bool>::value), "");
    static_assert((std::is_same<decltype(std::isnan((long double)0)), bool>::value), "");
    assert(std::isnan(-1.0) == false);
}
<commit_msg>fix copy and pasted comment in test<commit_after>//===----------------------------------------------------------------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is dual licensed under the MIT and the University of Illinois Open
// Source Licenses. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

// <cmath>

// isnan

// XFAIL: linux

#include <cmath>
#include <type_traits>
#include <cassert>

int main()
{
#ifdef isnan
#error isnan defined
#endif
    static_assert((std::is_same<decltype(std::isnan((float)0)), bool>::value), "");
    static_assert((std::is_same<decltype(std::isnan((double)0)), bool>::value), "");
    static_assert((std::is_same<decltype(std::isnan(0)), bool>::value), "");
    static_assert((std::is_same<decltype(std::isnan((long double)0)), bool>::value), "");
    assert(std::isnan(-1.0) == false);
}
<|endoftext|>


<commit_before>/** currency_js.cc                                 -*- C++ -*-
    Rémi Attab, 01 Mar 2013
    Copyright (c) 2013 Datacratic.  All rights reserved.

    JS wrapper for the currency classes.

*/

#include "currency_js.h"
#include "rtbkit/common/currency.h"
#include "soa/js/js_wrapped.h"
#include "soa/js/js_call.h"
#include "soa/js/js_utils.h"
#include "soa/js/js_registry.h"
#include "soa/sigslot/slot.h"

using namespace std;
using namespace v8;
using namespace node;
using namespace RTBKIT;

namespace Datacratic {
namespace JS {

/******************************************************************************/
/* AMOUNT JS                                                                  */
/******************************************************************************/

extern const char* const AmountName;
const char * const AmountName = "Amount";

struct AmountJS :
    public JSWrapped2<
        Amount,
        AmountJS,
        AmountName,
        bidRequestModule>
{
    AmountJS() {}

    AmountJS(
            v8::Handle<v8::Object> This,
            const std::shared_ptr<Amount>& amount =
                std::shared_ptr<Amount>())
    {
        HandleScope scope;
        wrap(This, amount);
    }

    static Handle<v8::Value>
    New(const Arguments& args)
    {
        try {
            string currency = getArg<string>(args, 1, "NONE", "currency");
            int64_t value = getArg<int64_t>(args, 2, 0, "value");

            cerr << "new amount " << currency << " " << value << endl;

            auto obj = std::make_shared<Amount>(currency, value);
            new AmountJS(args.This(), obj);

            return args.This();
        }
        HANDLE_JS_EXCEPTIONS;
    }

    static void
    Initialize()
    {
        Persistent<FunctionTemplate> t = Register(New);

        registerROProperty(&Amount::value, "value");
        registerROProperty(&Amount::getCurrencyStr, "currencyCode");

        registerMemberFn(&Amount::isZero, "isZero");
        registerMemberFn(&Amount::isNonNegative, "isNonNegative");
        registerMemberFn(&Amount::isNegative, "isNegative");

        registerMemberFn(&Amount::limit, "limit");
        registerMemberFn(&Amount::currencyIsCompatible, "currencyIsCompatible");

        // Typedef required to disambiguate the operator -
        typedef Amount (Amount::*SubOpFn)() const;

        registerMemberFn((SubOpFn)&Amount::operator-, "sub");
        registerMemberFn(&Amount::operator+, "add");
        registerMemberFn(&Amount::operator<, "lt");
        registerMemberFn(&Amount::operator<=, "le");
        registerMemberFn(&Amount::operator>, "gt");
        registerMemberFn(&Amount::operator>=, "ge");
        registerMemberFn(&Amount::operator==, "equals");

#if 0
        registerMemberFn(&Amount::toMicro, "toMicro");
        registerMemberFn(&Amount::toUnit, "toUnit");
        registerMemberFn(&Amount::toCPM, "toCPM");
        registerMemberFn(&Amount::toMicroCPM, "toMicroCPM");
#endif

        registerMemberFn(&Amount::getCurrencyStr, "currencyCode");

        //NODE_SET_PROTOTYPE_METHOD(t, "currencyCode", getCurrencyCode);
    }

    static Handle<Value>
    getCurrencyCode(const Arguments& args)
    {
        try {
            return Datacratic::JS::toJS(getShared(args)->getCurrencyStr());
        }
        HANDLE_JS_EXCEPTIONS;

        return Handle<Value>();
    }
};

Amount from_js(const JSValue& value, Amount*)
{
    return *AmountJS::fromJS(value);
}

Amount* from_js(const JSValue& value, Amount**)
{
    return AmountJS::fromJS(value).get();
}

void to_js(JS::JSValue& value, const Amount& amount)
{
    value = AmountJS::toJS(make_shared<Amount>(amount));
}

/******************************************************************************/
/* AMOUNT CONSTRUCTOR                                                         */
/******************************************************************************/

template<typename T, typename V>
Handle<Value> amountFn(const Arguments& args)
{
    try {
        V value = getArg<V>(args, 0, 0, "value");
        return AmountJS::toJS(make_shared<T>(value));
    }
    HANDLE_JS_EXCEPTIONS;
}

template<typename Fn>
void registerModuleFn(Handle<Object>& target, const string& name, Fn fn)
{
    auto tpl = Persistent<FunctionTemplate>::New(FunctionTemplate::New(fn));
    target->Set(String::NewSymbol(name.c_str()), tpl->GetFunction());
}

void initCurrencyFunctions(Handle<v8::Object>& target)
{
    registerModuleFn(target, "MicroUSD",     amountFn<MicroUSD, int64_t>);
    registerModuleFn(target, "USD",          amountFn<USD, double>);
    registerModuleFn(target, "USD_CPM",      amountFn<USD_CPM, double>);
    registerModuleFn(target, "MicroUSD_CPM", amountFn<MicroUSD_CPM, int64_t>);
}

} // namepsace JS
} // namespace Datacratic
<commit_msg>removed debug output<commit_after>/** currency_js.cc                                 -*- C++ -*-
    Rémi Attab, 01 Mar 2013
    Copyright (c) 2013 Datacratic.  All rights reserved.

    JS wrapper for the currency classes.

*/

#include "currency_js.h"
#include "rtbkit/common/currency.h"
#include "soa/js/js_wrapped.h"
#include "soa/js/js_call.h"
#include "soa/js/js_utils.h"
#include "soa/js/js_registry.h"
#include "soa/sigslot/slot.h"

using namespace std;
using namespace v8;
using namespace node;
using namespace RTBKIT;

namespace Datacratic {
namespace JS {

/******************************************************************************/
/* AMOUNT JS                                                                  */
/******************************************************************************/

extern const char* const AmountName;
const char * const AmountName = "Amount";

struct AmountJS :
    public JSWrapped2<
        Amount,
        AmountJS,
        AmountName,
        bidRequestModule>
{
    AmountJS() {}

    AmountJS(
            v8::Handle<v8::Object> This,
            const std::shared_ptr<Amount>& amount =
                std::shared_ptr<Amount>())
    {
        HandleScope scope;
        wrap(This, amount);
    }

    static Handle<v8::Value>
    New(const Arguments& args)
    {
        try {
            string currency = getArg<string>(args, 1, "NONE", "currency");
            int64_t value = getArg<int64_t>(args, 2, 0, "value");

            //cerr << "new amount " << currency << " " << value << endl;

            auto obj = std::make_shared<Amount>(currency, value);
            new AmountJS(args.This(), obj);

            return args.This();
        }
        HANDLE_JS_EXCEPTIONS;
    }

    static void
    Initialize()
    {
        Persistent<FunctionTemplate> t = Register(New);

        registerROProperty(&Amount::value, "value");
        registerROProperty(&Amount::getCurrencyStr, "currencyCode");

        registerMemberFn(&Amount::isZero, "isZero");
        registerMemberFn(&Amount::isNonNegative, "isNonNegative");
        registerMemberFn(&Amount::isNegative, "isNegative");

        registerMemberFn(&Amount::limit, "limit");
        registerMemberFn(&Amount::currencyIsCompatible, "currencyIsCompatible");

        // Typedef required to disambiguate the operator -
        typedef Amount (Amount::*SubOpFn)() const;

        registerMemberFn((SubOpFn)&Amount::operator-, "sub");
        registerMemberFn(&Amount::operator+, "add");
        registerMemberFn(&Amount::operator<, "lt");
        registerMemberFn(&Amount::operator<=, "le");
        registerMemberFn(&Amount::operator>, "gt");
        registerMemberFn(&Amount::operator>=, "ge");
        registerMemberFn(&Amount::operator==, "equals");

#if 0
        registerMemberFn(&Amount::toMicro, "toMicro");
        registerMemberFn(&Amount::toUnit, "toUnit");
        registerMemberFn(&Amount::toCPM, "toCPM");
        registerMemberFn(&Amount::toMicroCPM, "toMicroCPM");
#endif

        registerMemberFn(&Amount::getCurrencyStr, "currencyCode");

        //NODE_SET_PROTOTYPE_METHOD(t, "currencyCode", getCurrencyCode);
    }

    static Handle<Value>
    getCurrencyCode(const Arguments& args)
    {
        try {
            return Datacratic::JS::toJS(getShared(args)->getCurrencyStr());
        }
        HANDLE_JS_EXCEPTIONS;

        return Handle<Value>();
    }
};

Amount from_js(const JSValue& value, Amount*)
{
    return *AmountJS::fromJS(value);
}

Amount* from_js(const JSValue& value, Amount**)
{
    return AmountJS::fromJS(value).get();
}

void to_js(JS::JSValue& value, const Amount& amount)
{
    value = AmountJS::toJS(make_shared<Amount>(amount));
}

/******************************************************************************/
/* AMOUNT CONSTRUCTOR                                                         */
/******************************************************************************/

template<typename T, typename V>
Handle<Value> amountFn(const Arguments& args)
{
    try {
        V value = getArg<V>(args, 0, 0, "value");
        return AmountJS::toJS(make_shared<T>(value));
    }
    HANDLE_JS_EXCEPTIONS;
}

template<typename Fn>
void registerModuleFn(Handle<Object>& target, const string& name, Fn fn)
{
    auto tpl = Persistent<FunctionTemplate>::New(FunctionTemplate::New(fn));
    target->Set(String::NewSymbol(name.c_str()), tpl->GetFunction());
}

void initCurrencyFunctions(Handle<v8::Object>& target)
{
    registerModuleFn(target, "MicroUSD",     amountFn<MicroUSD, int64_t>);
    registerModuleFn(target, "USD",          amountFn<USD, double>);
    registerModuleFn(target, "USD_CPM",      amountFn<USD_CPM, double>);
    registerModuleFn(target, "MicroUSD_CPM", amountFn<MicroUSD_CPM, int64_t>);
}

} // namepsace JS
} // namespace Datacratic
<|endoftext|>


<commit_before>#include "Hierarchy.h"
#include "Application.h"
#include "ModuleEditor.h"

#include "GameObject.h"
#include "Component.h"
#include "ComponentTransform.h"
#include "ComponentLight.h"
#include "ComponentCar.h"
#include "ComponentScript.h"

#include "ModuleGOManager.h"
#include "LayerSystem.h"

#include "ModuleInput.h"
#include "ModuleResourceManager.h"
#include "ModuleCamera3D.h"

#include "ModuleScripting.h"

#include "SDL/include/SDL_scancode.h"

Hierarchy::Hierarchy()
{
	active = true;
	flags |= ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoMove;
}
Hierarchy::~Hierarchy()
{}

void Hierarchy::Draw()
{
	if (!active) return;

	ImGui::SetNextWindowSize(current_size);
	ImGui::SetNextWindowPos(current_position);

	ImGui::Begin("Hierarchy", &active, flags);

	DisplayGameObjectsChilds(App->go_manager->root->GetChilds());

	if (ImGui::IsMouseHoveringWindow())
	{
		if (ImGui::IsMouseClicked(1))
		{
			ImGui::OpenPopup("HierarchyOptions");
		}
	}

	if (ImGui::BeginPopup("HierarchyOptions"))
	{
		if (ImGui::MenuItem("Duplicate"))
		{
			if (App->editor->selected.size() > 0)
				App->go_manager->DuplicateGameObject(App->editor->selected.back());
		}

		if (ImGui::MenuItem("Delete"))
		{
			App->editor->RemoveSelected();
		}
		ImGui::Separator();
		if (ImGui::MenuItem("Create Prefab"))
		{
			if (App->editor->selected.size() > 0)
			{
				App->resource_manager->SavePrefab(App->editor->selected.back());
				App->editor->RefreshAssets();
			}
		}
		ImGui::Separator();
		if (ImGui::MenuItem("Create Empty"))
		{
			GameObject* game_object = (App->editor->selected.size() > 0) ? App->editor->selected.back() : nullptr;
			App->editor->SelectSingle(App->go_manager->CreateGameObject(game_object));
		}
		if (ImGui::BeginMenu("3D Object"))
		{
			if (ImGui::MenuItem("Cube"))
				App->go_manager->CreatePrimitive(PrimitiveType::P_CUBE);

			if (ImGui::MenuItem("Sphere"))
				App->go_manager->CreatePrimitive(PrimitiveType::P_SPHERE);

			if (ImGui::MenuItem("Plane"))
				App->go_manager->CreatePrimitive(PrimitiveType::P_PLANE);

			if (ImGui::MenuItem("Cylinder"))
				App->go_manager->CreatePrimitive(PrimitiveType::P_CYLINDER);

			if (ImGui::BeginMenu("Light"))
			{
				if (ImGui::MenuItem("Directional Light"))
				{
					App->go_manager->CreateLight(nullptr, DIRECTIONAL_LIGHT);
				}
				ImGui::EndMenu();
			}
			ImGui::EndMenu();
		}

		if (ImGui::MenuItem("Set Parent"))
		{
			setting_parent = true;
		}

		ImGui::EndPopup();
	}

	// Quick test for unselecting game objects when not selecting none
	int size_x = current_size.x;
	int size_y = current_size.y - ImGui::GetCursorPosY() - 10;
	ImGui::SetCursorPosX(0);
	if (ImGui::InvisibleButton("test: unselect GO", ImVec2(size_x, size_y)))
	{
		if (setting_parent == true)
		{
			setting_parent = false;
			if (App->editor->selected.empty() == false)
			{
				child_to_set = App->editor->selected.back();
				child_to_set->SetParent(App->go_manager->root);
			}
			parent_to_set = child_to_set = nullptr;
		}
		else if (App->scripting->setting_go_var_name != "")
		{
			if (App->scripting->to_set_var != nullptr)
				App->scripting->to_set_var->SetGOVar(nullptr);
		}
		else
		{
			App->editor->UnselectAll();
		}
	}

	if (set_parent_now == true)
	{
		set_parent_now = false;
		setting_parent = false;
		child_to_set->SetParent(parent_to_set);
		parent_to_set = child_to_set = nullptr;
	}

	ImGui::End();
}

void Hierarchy::DisplayGameObjectsChilds(const std::vector<GameObject*>* childs)
{
	for (std::vector<GameObject*>::const_iterator object = (*childs).begin(); object != (*childs).end(); ++object)
	{
		uint flags = ImGuiTreeNodeFlags_OpenOnArrow;
		if (App->editor->IsSelected(*object))
			flags |= ImGuiTreeNodeFlags_Selected;

		if ((*object)->ChildCount() == 0)
			flags |= ImGuiTreeNodeFlags_Leaf | ImGuiTreeNodeFlags_NoTreePushOnOpen;

		if ((*object)->IsActive() == false)
			ImGui::PushStyleColor(ImGuiCol_Text, ImVec4(0.5, 0.5, 0.5, 0.4));

		ImGui::PushID((*object)->GetUUID());
		bool open = ImGui::TreeNodeEx((*object)->name.data(), flags);
		if ((*object)->IsActive() == false)
			ImGui::PopStyleColor();
		bool hasChilds = (*object)->ChildCount() > 0;
		ImGui::PopID();
		if (ImGui::IsItemHovered() && ImGui::IsMouseDoubleClicked(0))
		{
			App->camera->Center((*object)->transform->GetGlobalMatrix().TranslatePart());
		}

		if (ImGui::IsItemClicked(0) || ImGui::IsItemClicked(1))
		{
			if (setting_parent == true)
			{
				if (App->editor->selected.size() > 0)
				{
					parent_to_set = *object;
					child_to_set = App->editor->selected.back();
					set_parent_now = true;
					App->editor->UnselectAll();
					break;
				}
				setting_parent = false;
			}
			else if (App->scripting->setting_go_var_name != "")
			{
				if (App->scripting->to_set_var != nullptr)
				{
					App->scripting->to_set_var->SetGOVar(*object);
				}
				else
				{
					App->scripting->setting_go_var_name = "";
				}
			}
			else if (App->editor->assign_wheel != -1)
			{
				App->editor->wheel_assign = *object;
			}
			else
			{
				OnClickSelect(*object);
			}
		}

		if (hasChilds && open)
		{
			DisplayGameObjectsChilds((*object)->GetChilds());
			ImGui::TreePop();
		}
	}
}

void Hierarchy::OnClickSelect(GameObject* game_object)
{
	if (App->input->GetKey(SDL_SCANCODE_LSHIFT) == KEY_REPEAT || App->input->GetKey(SDL_SCANCODE_RSHIFT) == KEY_REPEAT ||
		App->input->GetKey(SDL_SCANCODE_LCTRL) == KEY_REPEAT || App->input->GetKey(SDL_SCANCODE_RCTRL) == KEY_REPEAT)
	{
		if (App->editor->IsSelected(game_object))
		{
			App->editor->Unselect(game_object);
		}
		else
		{
			App->editor->AddSelect(game_object);
		}
	}
	else
	{
		App->editor->SelectSingle(game_object);
	}
}<commit_msg>Multiple set-parent childs<commit_after>#include "Hierarchy.h"
#include "Application.h"
#include "ModuleEditor.h"

#include "GameObject.h"
#include "Component.h"
#include "ComponentTransform.h"
#include "ComponentLight.h"
#include "ComponentCar.h"
#include "ComponentScript.h"

#include "ModuleGOManager.h"
#include "LayerSystem.h"

#include "ModuleInput.h"
#include "ModuleResourceManager.h"
#include "ModuleCamera3D.h"

#include "ModuleScripting.h"

#include "SDL/include/SDL_scancode.h"

Hierarchy::Hierarchy()
{
	active = true;
	//flags |= ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoMove;
}
Hierarchy::~Hierarchy()
{}

void Hierarchy::Draw()
{
	if (!active) return;

	ImGui::SetNextWindowSize(current_size);
	ImGui::SetNextWindowPos(current_position);

	ImGui::Begin("Hierarchy", &active, flags);
	current_size = ImGui::GetWindowSize();
	DisplayGameObjectsChilds(App->go_manager->root->GetChilds());

	if (ImGui::IsMouseHoveringWindow())
	{
		if (ImGui::IsMouseClicked(1))
		{
			ImGui::OpenPopup("HierarchyOptions");
		}
	}

	if (ImGui::BeginPopup("HierarchyOptions"))
	{
		if (ImGui::MenuItem("Duplicate"))
		{
			if (App->editor->selected.size() > 0)
				App->go_manager->DuplicateGameObject(App->editor->selected.back());
		}

		if (ImGui::MenuItem("Delete"))
		{
			App->editor->RemoveSelected();
		}
		ImGui::Separator();
		if (ImGui::MenuItem("Create Prefab"))
		{
			if (App->editor->selected.size() > 0)
			{
				App->resource_manager->SavePrefab(App->editor->selected.back());
				App->editor->RefreshAssets();
			}
		}
		ImGui::Separator();
		if (ImGui::MenuItem("Create Empty"))
		{
			GameObject* game_object = (App->editor->selected.size() > 0) ? App->editor->selected.back() : nullptr;
			App->editor->SelectSingle(App->go_manager->CreateGameObject(game_object));
		}
		if (ImGui::BeginMenu("3D Object"))
		{
			if (ImGui::MenuItem("Cube"))
				App->go_manager->CreatePrimitive(PrimitiveType::P_CUBE);

			if (ImGui::MenuItem("Sphere"))
				App->go_manager->CreatePrimitive(PrimitiveType::P_SPHERE);

			if (ImGui::MenuItem("Plane"))
				App->go_manager->CreatePrimitive(PrimitiveType::P_PLANE);

			if (ImGui::MenuItem("Cylinder"))
				App->go_manager->CreatePrimitive(PrimitiveType::P_CYLINDER);

			if (ImGui::BeginMenu("Light"))
			{
				if (ImGui::MenuItem("Directional Light"))
				{
					App->go_manager->CreateLight(nullptr, DIRECTIONAL_LIGHT);
				}
				ImGui::EndMenu();
			}
			ImGui::EndMenu();
		}

		if (ImGui::MenuItem("Set Parent"))
		{
			setting_parent = true;
		}

		ImGui::EndPopup();
	}

	// Quick test for unselecting game objects when not selecting none
	int size_x = current_size.x;
	int size_y = current_size.y - ImGui::GetCursorPosY() - 10;
	ImGui::SetCursorPosX(0);
	if (ImGui::InvisibleButton("test: unselect GO", ImVec2(size_x, size_y)))
	{
		if (setting_parent == true)
		{
			setting_parent = false;
			if (App->editor->selected.empty() == false)
			{
				for (std::list<GameObject*>::iterator it = App->editor->selected.begin(); it != App->editor->selected.end(); ++it)
				{
					(*it)->SetParent(App->go_manager->root);
				}
				//child_to_set = App->editor->selected.back();
				//child_to_set->SetParent(App->go_manager->root);
			}
			parent_to_set = child_to_set = nullptr;
		}
		else if (App->scripting->setting_go_var_name != "")
		{
			if (App->scripting->to_set_var != nullptr)
				App->scripting->to_set_var->SetGOVar(nullptr);
		}
		else
		{
			App->editor->UnselectAll();
		}
	}

	if (set_parent_now == true)
	{
		set_parent_now = false;
		setting_parent = false;
		for (std::list<GameObject*>::iterator it = App->editor->selected.begin(); it != App->editor->selected.end(); ++it)
		{
			(*it)->SetParent(parent_to_set);
		}
		//child_to_set->SetParent(parent_to_set);
		parent_to_set = child_to_set = nullptr;
	}

	ImGui::End();
}

void Hierarchy::DisplayGameObjectsChilds(const std::vector<GameObject*>* childs)
{
	for (std::vector<GameObject*>::const_iterator object = (*childs).begin(); object != (*childs).end(); ++object)
	{
		uint flags = ImGuiTreeNodeFlags_OpenOnArrow;
		if (App->editor->IsSelected(*object))
			flags |= ImGuiTreeNodeFlags_Selected;

		if ((*object)->ChildCount() == 0)
			flags |= ImGuiTreeNodeFlags_Leaf | ImGuiTreeNodeFlags_NoTreePushOnOpen;

		if ((*object)->IsActive() == false)
			ImGui::PushStyleColor(ImGuiCol_Text, ImVec4(0.5, 0.5, 0.5, 0.4));

		ImGui::PushID((*object)->GetUUID());
		bool open = ImGui::TreeNodeEx((*object)->name.data(), flags);
		if ((*object)->IsActive() == false)
			ImGui::PopStyleColor();
		bool hasChilds = (*object)->ChildCount() > 0;
		ImGui::PopID();
		if (ImGui::IsItemHovered() && ImGui::IsMouseDoubleClicked(0))
		{
			App->camera->Center((*object)->transform->GetGlobalMatrix().TranslatePart());
		}

		if (ImGui::IsItemClicked(0) || ImGui::IsItemClicked(1))
		{
			if (setting_parent == true)
			{
				if (App->editor->selected.size() > 0)
				{
					parent_to_set = *object;
					child_to_set = App->editor->selected.back();
					set_parent_now = true;
					//App->editor->UnselectAll();
					break;
				}
				setting_parent = false;
			}
			else if (App->scripting->setting_go_var_name != "")
			{
				if (App->scripting->to_set_var != nullptr)
				{
					App->scripting->to_set_var->SetGOVar(*object);
				}
				else
				{
					App->scripting->setting_go_var_name = "";
				}
			}
			else if (App->editor->assign_wheel != -1)
			{
				App->editor->wheel_assign = *object;
			}
			else
			{
				OnClickSelect(*object);
			}
		}

		if (hasChilds && open)
		{
			DisplayGameObjectsChilds((*object)->GetChilds());
			ImGui::TreePop();
		}
	}
}

void Hierarchy::OnClickSelect(GameObject* game_object)
{
	if (App->input->GetKey(SDL_SCANCODE_LSHIFT) == KEY_REPEAT || App->input->GetKey(SDL_SCANCODE_RSHIFT) == KEY_REPEAT ||
		App->input->GetKey(SDL_SCANCODE_LCTRL) == KEY_REPEAT || App->input->GetKey(SDL_SCANCODE_RCTRL) == KEY_REPEAT)
	{
		if (App->editor->IsSelected(game_object))
		{
			App->editor->Unselect(game_object);
		}
		else
		{
			App->editor->AddSelect(game_object);
		}
	}
	else
	{
		App->editor->SelectSingle(game_object);
	}
}<|endoftext|>