<commit_before>/* Copyright 2019 The TensorFlow 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 "tensorflow/core/profiler/convert/xplane_to_op_metrics_db.h"

#include <algorithm>
#include <memory>
#include <vector>

#include "absl/algorithm/container.h"
#include "absl/container/flat_hash_map.h"
#include "absl/strings/str_cat.h"
#include "absl/strings/string_view.h"
#include "absl/types/optional.h"
#include "tensorflow/core/lib/gtl/map_util.h"
#include "tensorflow/core/platform/logging.h"
#include "tensorflow/core/platform/types.h"
#include "tensorflow/core/profiler/convert/op_metrics_db_combiner.h"
#include "tensorflow/core/profiler/convert/op_stack.h"
#include "tensorflow/core/profiler/protobuf/op_metrics.pb.h"
#include "tensorflow/core/profiler/protobuf/xplane.pb.h"
#include "tensorflow/core/profiler/utils/cost_utils.h"
#include "tensorflow/core/profiler/utils/op_metrics_db_utils.h"
#include "tensorflow/core/profiler/utils/op_utils.h"
#include "tensorflow/core/profiler/utils/tf_op_utils.h"
#include "tensorflow/core/profiler/utils/tf_xplane_visitor.h"
#include "tensorflow/core/profiler/utils/timespan.h"
#include "tensorflow/core/profiler/utils/trace_utils.h"
#include "tensorflow/core/profiler/utils/xplane_schema.h"
#include "tensorflow/core/profiler/utils/xplane_visitor.h"

namespace tensorflow {
namespace profiler {
namespace {

// Type of a TensorFlow Op activity, which is either beginning or ending an Op.
enum TfActivityType { kTfOpBegin, kTfOpEnd };

// Instant activity representing the begin or end of a host-side TF Op.
struct TfActivity {
  // The timestamp in picoseconds when this activity happened.
  uint64 timestamp_ps;
  // The ID of this Op.
  uint32 tf_op_id;
  // Type of this activity.
  TfActivityType activity_type;
  // Full TF op name and type of this activity (backed by XEvent::name).
  TfOp tf_op;
  // Whether it is eagerly executed.
  bool is_eager;
};

// TF Op metrics stored as element in OpStack.
struct TfOpInfo {
  explicit TfOpInfo(uint64 ts) : start_timestamp_ps(ts) {}

  // Start timestamp in picoseconds.
  uint64 start_timestamp_ps;
  // Children duration in picoseconds.
  uint64 children_duration_ps = 0;
};

// Processes a TF-activity on particular core.
void ProcessOneTfActivity(const TfActivity& activity,
                          OpStack<TfOpInfo>* tf_op_stack,
                          TfMetricsDbData* tf_metrics_data) {
  uint32 tf_op_id = activity.tf_op_id;
  switch (activity.activity_type) {
    case kTfOpBegin: {
      tf_op_stack->Push(tf_op_id,
                        absl::make_unique<TfOpInfo>(activity.timestamp_ps));
      break;
    }
    case kTfOpEnd: {
      std::unique_ptr<TfOpInfo> info = tf_op_stack->Pop(tf_op_id);
      if (info == nullptr) {
        // This happens if TraceMes overlap.
        VLOG(1) << "No begin event found for TF activity id=" << tf_op_id
                << " name=" << activity.tf_op.name
                << " type=" << activity.tf_op.type;
        break;
      }
      Timespan tf_op_span =
          PicoSpan(info->start_timestamp_ps, activity.timestamp_ps);
      tf_metrics_data->tf_metrics_db_builder.EnterOp(
          activity.tf_op.name, activity.tf_op.type, activity.is_eager,
          tf_op_span.duration_ps(), info->children_duration_ps);
      TfOpInfo* parent_info = tf_op_stack->Top();
      if (parent_info != nullptr) {
        parent_info->children_duration_ps += tf_op_span.duration_ps();
      }
      if (IsInfeedEnqueueOp(activity.tf_op.type)) {
        tf_metrics_data->tf_metrics_db_builder.EnterHostInfeedEnqueue(
            tf_op_span);
      }
      break;
    }
  }
}

// Processes all TF-activities on the given core.
void ProcessTfActivities(std::vector<TfActivity>* tf_activities,
                         TfMetricsDbData* tf_metrics_db_data) {
  if (tf_activities->empty()) return;
  absl::c_stable_sort(*tf_activities,
                      [](const TfActivity& a, const TfActivity& b) {
                        return a.timestamp_ps < b.timestamp_ps;
                      });
  OpStack<TfOpInfo> tf_op_stack;
  for (const auto& tf_activity : *tf_activities) {
    ProcessOneTfActivity(tf_activity, &tf_op_stack, tf_metrics_db_data);
  }
  SetTotalTimePs(
      tf_metrics_db_data->tf_metrics_db,
      tf_activities->back().timestamp_ps - tf_activities->front().timestamp_ps);
}

void CollectTfActivities(const XLineVisitor& line,
                         const absl::flat_hash_map<int64_t, TfOp>& tf_ops,
                         std::vector<TfActivity>* tf_activities) {
  uint32 tf_op_id = 0;
  tf_activities->reserve(line.NumEvents() * 2);
  line.ForEachEvent([&tf_ops, &tf_op_id,
                     &tf_activities](const XEventVisitor& event) {
    const TfOp* tf_op = gtl::FindOrNull(tf_ops, event.Id());
    if (tf_op != nullptr) {
      ++tf_op_id;
      bool is_eager = false;
      if (absl::optional<XStatVisitor> stat =
              event.GetStat(StatType::kIsEager)) {
        is_eager = stat->IntValue();
      }
      Timespan span = event.GetTimespan();
      tf_activities->push_back(
          {span.begin_ps(), tf_op_id, kTfOpBegin, *tf_op, is_eager});
      tf_activities->push_back(
          {span.end_ps(), tf_op_id, kTfOpEnd, *tf_op, is_eager});
    }
  });
}

}  // namespace

absl::flat_hash_map<int64_t, TfOp> CollectTfOpsFromHostThreadsXPlane(
    const XPlane& host_trace) {
  absl::flat_hash_map<int64_t, TfOp> tf_ops;
  for (const auto& id_metadata : host_trace.event_metadata()) {
    const XEventMetadata& metadata = id_metadata.second;
    // On the host, we have added some user-specified TraceMe's in addition to
    // the TraceMe's added to every TensorFlow op by the system. These
    // user-inserted TraceMe's have "unknown" type. We don't count them in
    // Tf-stats.
    TfOp tf_op = ParseTfOpFullname(metadata.name());
    if (tf_op.category != Category::kUnknown) {
      tf_ops.try_emplace(metadata.id(), tf_op);
    }
  }
  return tf_ops;
}

TfMetricsDbData ConvertHostThreadsXLineToTfMetricsDbData(
    const XLineVisitor& line,
    const absl::flat_hash_map<int64_t, TfOp>& tf_ops) {
  TfMetricsDbData tf_metrics_db_data;
  if (!tf_ops.empty()) {
    std::vector<TfActivity> tf_activities;
    CollectTfActivities(line, tf_ops, &tf_activities);
    ProcessTfActivities(&tf_activities, &tf_metrics_db_data);
  }
  return tf_metrics_db_data;
}

void ConsumeTfMetricsDbData(TfMetricsDbData src, OpMetricsDbCombiner* dst) {
  AddIdleOp(src.tf_metrics_db);
  dst->Combine(src.tf_metrics_db);
  src.tf_metrics_db.Clear();
}

OpMetricsDb ConvertHostThreadsXPlaneToOpMetricsDb(const XPlane& host_trace) {
  absl::flat_hash_map<int64_t, TfOp> tf_ops =
      CollectTfOpsFromHostThreadsXPlane(host_trace);
  OpMetricsDb result;
  OpMetricsDbCombiner combiner(&result);
  XPlaneVisitor plane = CreateTfXPlaneVisitor(&host_trace);
  plane.ForEachLine([&tf_ops, &combiner](const XLineVisitor& line) {
    ConsumeTfMetricsDbData(
        ConvertHostThreadsXLineToTfMetricsDbData(line, tf_ops), &combiner);
  });
  return result;
}

OpMetricsDb ConvertDeviceTraceXPlaneToOpMetricsDb(const XPlane& device_trace) {
  OpMetricsDb result;
  DeviceOpMetricsDbBuilder device_op_metrics_db_builder(&result);

  int64_t first_op_offset_ps = kint64max;
  int64_t last_op_offset_ps = 0;

  TfOpRoofLineCostEstimator op_level_cost_estimator;
  XPlaneVisitor plane = CreateTfXPlaneVisitor(&device_trace);
  plane.ForEachLine([&](const XLineVisitor& line) {
    if (IsDerivedThreadId(line.Id())) return;
    line.ForEachEvent([&](const XEventVisitor& event) {
      first_op_offset_ps = std::min(first_op_offset_ps, event.OffsetPs());
      last_op_offset_ps = std::max(last_op_offset_ps, event.EndOffsetPs());

      absl::string_view tf_op_full_name;
      bool is_eager;
      event.ForEachStat([&](const XStatVisitor& stat) {
        if (stat.Type() == StatType::kLevel0 ||  // old way to deliver tf_op.
            stat.Type() == StatType::kTfOp) {
          tf_op_full_name = stat.StrOrRefValue();
        } else if (stat.Type() == StatType::kIsEager) {
          is_eager = stat.IntValue();
        }
      });
      if (tf_op_full_name.empty()) return;
      TfOp tf_op = ParseTfOpFullname(tf_op_full_name);
      TfOpRoofLineCostEstimator::OpRoofLineStats costs;
      if (tf_op.category != Category::kUnknown) {
        costs = op_level_cost_estimator.Predict(event);
      }
      device_op_metrics_db_builder.EnterOp(
          /*program_id=*/0, absl::StrCat(tf_op.name, "/", event.Name()),
          tf_op.type, tf_op_full_name, is_eager,
          /*occurrences=*/1, event.DurationPs(),
          /*children_time_ps=*/0, costs.flops, costs.bytes_accessed);
    });
  });
  SetTotalTimePs(
      result, last_op_offset_ps ? last_op_offset_ps - first_op_offset_ps : 0);
  AddIdleOp(result);
  return result;
}

}  // namespace profiler
}  // namespace tensorflow
<commit_msg>Fix use of uninitialized value<commit_after>/* Copyright 2019 The TensorFlow 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 "tensorflow/core/profiler/convert/xplane_to_op_metrics_db.h"

#include <algorithm>
#include <memory>
#include <vector>

#include "absl/algorithm/container.h"
#include "absl/container/flat_hash_map.h"
#include "absl/strings/str_cat.h"
#include "absl/strings/string_view.h"
#include "absl/types/optional.h"
#include "tensorflow/core/lib/gtl/map_util.h"
#include "tensorflow/core/platform/logging.h"
#include "tensorflow/core/platform/types.h"
#include "tensorflow/core/profiler/convert/op_metrics_db_combiner.h"
#include "tensorflow/core/profiler/convert/op_stack.h"
#include "tensorflow/core/profiler/protobuf/op_metrics.pb.h"
#include "tensorflow/core/profiler/protobuf/xplane.pb.h"
#include "tensorflow/core/profiler/utils/cost_utils.h"
#include "tensorflow/core/profiler/utils/op_metrics_db_utils.h"
#include "tensorflow/core/profiler/utils/op_utils.h"
#include "tensorflow/core/profiler/utils/tf_op_utils.h"
#include "tensorflow/core/profiler/utils/tf_xplane_visitor.h"
#include "tensorflow/core/profiler/utils/timespan.h"
#include "tensorflow/core/profiler/utils/trace_utils.h"
#include "tensorflow/core/profiler/utils/xplane_schema.h"
#include "tensorflow/core/profiler/utils/xplane_visitor.h"

namespace tensorflow {
namespace profiler {
namespace {

// Type of a TensorFlow Op activity, which is either beginning or ending an Op.
enum TfActivityType { kTfOpBegin, kTfOpEnd };

// Instant activity representing the begin or end of a host-side TF Op.
struct TfActivity {
  // The timestamp in picoseconds when this activity happened.
  uint64 timestamp_ps;
  // The ID of this Op.
  uint32 tf_op_id;
  // Type of this activity.
  TfActivityType activity_type;
  // Full TF op name and type of this activity (backed by XEvent::name).
  TfOp tf_op;
  // Whether it is eagerly executed.
  bool is_eager;
};

// TF Op metrics stored as element in OpStack.
struct TfOpInfo {
  explicit TfOpInfo(uint64 ts) : start_timestamp_ps(ts) {}

  // Start timestamp in picoseconds.
  uint64 start_timestamp_ps;
  // Children duration in picoseconds.
  uint64 children_duration_ps = 0;
};

// Processes a TF-activity on particular core.
void ProcessOneTfActivity(const TfActivity& activity,
                          OpStack<TfOpInfo>* tf_op_stack,
                          TfMetricsDbData* tf_metrics_data) {
  uint32 tf_op_id = activity.tf_op_id;
  switch (activity.activity_type) {
    case kTfOpBegin: {
      tf_op_stack->Push(tf_op_id,
                        absl::make_unique<TfOpInfo>(activity.timestamp_ps));
      break;
    }
    case kTfOpEnd: {
      std::unique_ptr<TfOpInfo> info = tf_op_stack->Pop(tf_op_id);
      if (info == nullptr) {
        // This happens if TraceMes overlap.
        VLOG(1) << "No begin event found for TF activity id=" << tf_op_id
                << " name=" << activity.tf_op.name
                << " type=" << activity.tf_op.type;
        break;
      }
      Timespan tf_op_span =
          PicoSpan(info->start_timestamp_ps, activity.timestamp_ps);
      tf_metrics_data->tf_metrics_db_builder.EnterOp(
          activity.tf_op.name, activity.tf_op.type, activity.is_eager,
          tf_op_span.duration_ps(), info->children_duration_ps);
      TfOpInfo* parent_info = tf_op_stack->Top();
      if (parent_info != nullptr) {
        parent_info->children_duration_ps += tf_op_span.duration_ps();
      }
      if (IsInfeedEnqueueOp(activity.tf_op.type)) {
        tf_metrics_data->tf_metrics_db_builder.EnterHostInfeedEnqueue(
            tf_op_span);
      }
      break;
    }
  }
}

// Processes all TF-activities on the given core.
void ProcessTfActivities(std::vector<TfActivity>* tf_activities,
                         TfMetricsDbData* tf_metrics_db_data) {
  if (tf_activities->empty()) return;
  absl::c_stable_sort(*tf_activities,
                      [](const TfActivity& a, const TfActivity& b) {
                        return a.timestamp_ps < b.timestamp_ps;
                      });
  OpStack<TfOpInfo> tf_op_stack;
  for (const auto& tf_activity : *tf_activities) {
    ProcessOneTfActivity(tf_activity, &tf_op_stack, tf_metrics_db_data);
  }
  SetTotalTimePs(
      tf_metrics_db_data->tf_metrics_db,
      tf_activities->back().timestamp_ps - tf_activities->front().timestamp_ps);
}

void CollectTfActivities(const XLineVisitor& line,
                         const absl::flat_hash_map<int64_t, TfOp>& tf_ops,
                         std::vector<TfActivity>* tf_activities) {
  uint32 tf_op_id = 0;
  tf_activities->reserve(line.NumEvents() * 2);
  line.ForEachEvent([&tf_ops, &tf_op_id,
                     &tf_activities](const XEventVisitor& event) {
    const TfOp* tf_op = gtl::FindOrNull(tf_ops, event.Id());
    if (tf_op != nullptr) {
      ++tf_op_id;
      bool is_eager = false;
      if (absl::optional<XStatVisitor> stat =
              event.GetStat(StatType::kIsEager)) {
        is_eager = stat->IntValue();
      }
      Timespan span = event.GetTimespan();
      tf_activities->push_back(
          {span.begin_ps(), tf_op_id, kTfOpBegin, *tf_op, is_eager});
      tf_activities->push_back(
          {span.end_ps(), tf_op_id, kTfOpEnd, *tf_op, is_eager});
    }
  });
}

}  // namespace

absl::flat_hash_map<int64_t, TfOp> CollectTfOpsFromHostThreadsXPlane(
    const XPlane& host_trace) {
  absl::flat_hash_map<int64_t, TfOp> tf_ops;
  for (const auto& id_metadata : host_trace.event_metadata()) {
    const XEventMetadata& metadata = id_metadata.second;
    // On the host, we have added some user-specified TraceMe's in addition to
    // the TraceMe's added to every TensorFlow op by the system. These
    // user-inserted TraceMe's have "unknown" type. We don't count them in
    // Tf-stats.
    TfOp tf_op = ParseTfOpFullname(metadata.name());
    if (tf_op.category != Category::kUnknown) {
      tf_ops.try_emplace(metadata.id(), tf_op);
    }
  }
  return tf_ops;
}

TfMetricsDbData ConvertHostThreadsXLineToTfMetricsDbData(
    const XLineVisitor& line,
    const absl::flat_hash_map<int64_t, TfOp>& tf_ops) {
  TfMetricsDbData tf_metrics_db_data;
  if (!tf_ops.empty()) {
    std::vector<TfActivity> tf_activities;
    CollectTfActivities(line, tf_ops, &tf_activities);
    ProcessTfActivities(&tf_activities, &tf_metrics_db_data);
  }
  return tf_metrics_db_data;
}

void ConsumeTfMetricsDbData(TfMetricsDbData src, OpMetricsDbCombiner* dst) {
  AddIdleOp(src.tf_metrics_db);
  dst->Combine(src.tf_metrics_db);
  src.tf_metrics_db.Clear();
}

OpMetricsDb ConvertHostThreadsXPlaneToOpMetricsDb(const XPlane& host_trace) {
  absl::flat_hash_map<int64_t, TfOp> tf_ops =
      CollectTfOpsFromHostThreadsXPlane(host_trace);
  OpMetricsDb result;
  OpMetricsDbCombiner combiner(&result);
  XPlaneVisitor plane = CreateTfXPlaneVisitor(&host_trace);
  plane.ForEachLine([&tf_ops, &combiner](const XLineVisitor& line) {
    ConsumeTfMetricsDbData(
        ConvertHostThreadsXLineToTfMetricsDbData(line, tf_ops), &combiner);
  });
  return result;
}

OpMetricsDb ConvertDeviceTraceXPlaneToOpMetricsDb(const XPlane& device_trace) {
  OpMetricsDb result;
  DeviceOpMetricsDbBuilder device_op_metrics_db_builder(&result);

  int64_t first_op_offset_ps = kint64max;
  int64_t last_op_offset_ps = 0;

  TfOpRoofLineCostEstimator op_level_cost_estimator;
  XPlaneVisitor plane = CreateTfXPlaneVisitor(&device_trace);
  plane.ForEachLine([&](const XLineVisitor& line) {
    if (IsDerivedThreadId(line.Id())) return;
    line.ForEachEvent([&](const XEventVisitor& event) {
      first_op_offset_ps = std::min(first_op_offset_ps, event.OffsetPs());
      last_op_offset_ps = std::max(last_op_offset_ps, event.EndOffsetPs());

      absl::string_view tf_op_full_name;
      bool is_eager = false;
      event.ForEachStat([&](const XStatVisitor& stat) {
        if (stat.Type() == StatType::kLevel0 ||  // old way to deliver tf_op.
            stat.Type() == StatType::kTfOp) {
          tf_op_full_name = stat.StrOrRefValue();
        } else if (stat.Type() == StatType::kIsEager) {
          is_eager = stat.IntValue();
        }
      });
      if (tf_op_full_name.empty()) return;
      TfOp tf_op = ParseTfOpFullname(tf_op_full_name);
      TfOpRoofLineCostEstimator::OpRoofLineStats costs;
      if (tf_op.category != Category::kUnknown) {
        costs = op_level_cost_estimator.Predict(event);
      }
      device_op_metrics_db_builder.EnterOp(
          /*program_id=*/0, absl::StrCat(tf_op.name, "/", event.Name()),
          tf_op.type, tf_op_full_name, is_eager,
          /*occurrences=*/1, event.DurationPs(),
          /*children_time_ps=*/0, costs.flops, costs.bytes_accessed);
    });
  });
  SetTotalTimePs(
      result, last_op_offset_ps ? last_op_offset_ps - first_op_offset_ps : 0);
  AddIdleOp(result);
  return result;
}

}  // namespace profiler
}  // namespace tensorflow
<|endoftext|>


<commit_before>#include "window.hpp"
#include <GLFW/glfw3.h>
#include <utility>
#include <cmath>

int main(int argc, char* argv[])
{
  Window win{std::make_pair(800,800)};

  while (!win.should_close()) {
    if (win.get_key(GLFW_KEY_ESCAPE) == GLFW_PRESS) {
      win.close();
    }

    bool left_pressed = win.get_mouse_button(GLFW_MOUSE_BUTTON_LEFT) == GLFW_PRESS;

    auto t = win.get_time();

    float x1 = 400.f + 380.f * std::sin(t);
    float y1 = 400.f + 380.f * std::cos(t);

    float x2 = 400.f + 380.f * std::sin(2.0f*t);
    float y2 = 400.f + 380.f * std::cos(2.0f*t);

    float x3 = 400.f + 380.f * std::sin(t-10.f);
    float y3 = 400.f + 380.f * std::cos(t-10.f);

    win.draw_point(x1, y1, 1.0f, 0.0f, 0.0f);
    win.draw_point(x2, y2, 0.0f, 1.0f, 0.0f);
    win.draw_point(x3, y3, 0.0f, 0.0f, 1.0f);

    auto mouse_position = win.mouse_position();
    if (left_pressed) {
      win.draw_line(30.0f, 30.0f, // FROM pixel idx with coords (x=30, y=30)
                    mouse_position.first, mouse_position.second, // TO mouse position in pixel coords
                    1.0,0.0,0.0, // color with r,g,b in [0.0, 1.0]
                    2.0);        // line thickness = 1.0 * default thickness
    }

    win.draw_line(0, mouse_position.second, 10, mouse_position.second, 0.0, 0.0, 0.0);
    win.draw_line(win.window_size().second - 10, mouse_position.second, win.window_size().second, mouse_position.second, 0.0, 0.0, 0.0);

    win.draw_line(mouse_position.first, 0, mouse_position.first, 10, 0.0, 0.0, 0.0);
    win.draw_line(mouse_position.first, win.window_size().second - 10, mouse_position.first, win.window_size().second, 0.0, 0.0, 0.0);

    std::string display_text = "mouse position: (" + std::to_string(mouse_position.first) + ", " + std::to_string(mouse_position.second) + ")";

    int text_offset_x = 10;
    int text_offset_y = 5;
    unsigned int font_size = 35;

    win.draw_text(text_offset_x, text_offset_y, font_size, display_text);

    win.update();
  }

  return 0;
}
<commit_msg>reset default line thickness in example.cpp<commit_after>#include "window.hpp"
#include <GLFW/glfw3.h>
#include <utility>
#include <cmath>

int main(int argc, char* argv[])
{
  Window win{std::make_pair(800,800)};

  while (!win.should_close()) {
    if (win.get_key(GLFW_KEY_ESCAPE) == GLFW_PRESS) {
      win.close();
    }

    bool left_pressed = win.get_mouse_button(GLFW_MOUSE_BUTTON_LEFT) == GLFW_PRESS;

    auto t = win.get_time();

    float x1 = 400.f + 380.f * std::sin(t);
    float y1 = 400.f + 380.f * std::cos(t);

    float x2 = 400.f + 380.f * std::sin(2.0f*t);
    float y2 = 400.f + 380.f * std::cos(2.0f*t);

    float x3 = 400.f + 380.f * std::sin(t-10.f);
    float y3 = 400.f + 380.f * std::cos(t-10.f);

    win.draw_point(x1, y1, 1.0f, 0.0f, 0.0f);
    win.draw_point(x2, y2, 0.0f, 1.0f, 0.0f);
    win.draw_point(x3, y3, 0.0f, 0.0f, 1.0f);

    auto mouse_position = win.mouse_position();
    if (left_pressed) {
      win.draw_line(30.0f, 30.0f, // FROM pixel idx with coords (x=30, y=30)
                    mouse_position.first, mouse_position.second, // TO mouse position in pixel coords
                    1.0,0.0,0.0, // color with r,g,b in [0.0, 1.0]
                    1.0);        // line thickness = 1.0 * default thickness
    }

    win.draw_line(0, mouse_position.second, 10, mouse_position.second, 0.0, 0.0, 0.0);
    win.draw_line(win.window_size().second - 10, mouse_position.second, win.window_size().second, mouse_position.second, 0.0, 0.0, 0.0);

    win.draw_line(mouse_position.first, 0, mouse_position.first, 10, 0.0, 0.0, 0.0);
    win.draw_line(mouse_position.first, win.window_size().second - 10, mouse_position.first, win.window_size().second, 0.0, 0.0, 0.0);

    std::string display_text = "mouse position: (" + std::to_string(mouse_position.first) + ", " + std::to_string(mouse_position.second) + ")";

    int text_offset_x = 10;
    int text_offset_y = 5;
    unsigned int font_size = 35;

    win.draw_text(text_offset_x, text_offset_y, font_size, display_text);

    win.update();
  }

  return 0;
}
<|endoftext|>


<commit_before>/*
 * Copyright 2007-2020 Content Management AG
 * All rights reserved.
 *
 * author: Max Kellermann <mk@cm4all.com>
 *
 * 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 AND CONTRIBUTORS
 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE
 * FOUNDATION 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 "BalancerMap.hxx"
#include "AddressListWrapper.hxx"
#include "PickGeneric.hxx"
#include "RoundRobinBalancer.cxx"
#include "AddressList.hxx"

SocketAddress
BalancerMap::Get(const Expiry now,
		 const AddressList &list, sticky_hash_t sticky_hash) noexcept
{
	return PickGeneric(now, list.sticky_mode,
			   MakeAddressListWrapper(AddressListWrapper(failure_manager,
								     list.addresses)),
			   sticky_hash);
}

inline RoundRobinBalancer &
BalancerMap::MakeRoundRobinBalancer(HashKey key) noexcept
{
	auto *item = cache.Get(key);

	if (item == nullptr)
		/* create a new cache item */
		item = &cache.Put(std::move(key), RoundRobinBalancer());

	return *item;
}
<commit_msg>cluster/BalancerMap: remove misplaced `inline`<commit_after>/*
 * Copyright 2007-2020 Content Management AG
 * All rights reserved.
 *
 * author: Max Kellermann <mk@cm4all.com>
 *
 * 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 AND CONTRIBUTORS
 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE
 * FOUNDATION 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 "BalancerMap.hxx"
#include "AddressListWrapper.hxx"
#include "PickGeneric.hxx"
#include "RoundRobinBalancer.cxx"
#include "AddressList.hxx"

SocketAddress
BalancerMap::Get(const Expiry now,
		 const AddressList &list, sticky_hash_t sticky_hash) noexcept
{
	return PickGeneric(now, list.sticky_mode,
			   MakeAddressListWrapper(AddressListWrapper(failure_manager,
								     list.addresses)),
			   sticky_hash);
}

RoundRobinBalancer &
BalancerMap::MakeRoundRobinBalancer(HashKey key) noexcept
{
	auto *item = cache.Get(key);

	if (item == nullptr)
		/* create a new cache item */
		item = &cache.Put(std::move(key), RoundRobinBalancer());

	return *item;
}
<|endoftext|>


<commit_before>/*
 * Copyright (c) Meta Platforms, Inc. and affiliates.
 *
 * This source code is licensed under the MIT license found in the
 * LICENSE file in the root directory of this source tree.
 */

#ifdef FB_SONARKIT_ENABLED

#include "WebSocketTLSClient.h"
#include <Flipper/ConnectionContextStore.h>
#include <Flipper/FlipperTransportTypes.h>
#include <Flipper/FlipperURLSerializer.h>
#include <Flipper/Log.h>
#include <folly/String.h>
#include <folly/futures/Future.h>
#include <folly/io/async/AsyncSocketException.h>
#include <folly/io/async/SSLContext.h>
#include <folly/json.h>
#include <websocketpp/common/memory.hpp>
#include <websocketpp/common/thread.hpp>
#include <cctype>
#include <iomanip>
#include <sstream>
#include <stdexcept>
#include <string>
#include <thread>

namespace facebook {
namespace flipper {

WebSocketTLSClient::WebSocketTLSClient(
    FlipperConnectionEndpoint endpoint,
    std::unique_ptr<FlipperSocketBasePayload> payload,
    folly::EventBase* eventBase)
    : WebSocketTLSClient(
          std::move(endpoint),
          std::move(payload),
          eventBase,
          nullptr) {}

WebSocketTLSClient::WebSocketTLSClient(
    FlipperConnectionEndpoint endpoint,
    std::unique_ptr<FlipperSocketBasePayload> payload,
    folly::EventBase* eventBase,
    ConnectionContextStore* connectionContextStore)
    : BaseClient(
          std::move(endpoint),
          std::move(payload),
          eventBase,
          connectionContextStore) {
  status_ = Status::Unconnected;

  socket_.clear_access_channels(websocketpp::log::alevel::all);
  socket_.clear_error_channels(websocketpp::log::elevel::all);
  socket_.init_asio();
  socket_.start_perpetual();

  thread_ = websocketpp::lib::make_shared<websocketpp::lib::thread>(
      &SocketTLSClient::run, &socket_);
}

WebSocketTLSClient::~WebSocketTLSClient() {
  disconnect();
}

bool WebSocketTLSClient::connect(FlipperConnectionManager* manager) {
  if (status_ != Status::Unconnected) {
    return false;
  }

  status_ = Status::Connecting;

  std::string connectionURL = endpoint_.secure ? "wss://" : "ws://";
  connectionURL += endpoint_.host;
  connectionURL += ":";
  connectionURL += std::to_string(endpoint_.port);

  auto serializer = URLSerializer{};
  payload_->serialize(serializer);
  auto payload = serializer.serialize();

  if (payload.size()) {
    connectionURL += "/?";
    connectionURL += payload;
  }

  socket_.set_tls_init_handler(bind(
      &WebSocketTLSClient::onTLSInit,
      this,
      endpoint_.host.c_str(),
      websocketpp::lib::placeholders::_1));

  auto uri = websocketpp::lib::make_shared<websocketpp::uri>(connectionURL);
  websocketpp::lib::error_code ec;
  connection_ = socket_.get_connection(uri, ec);

  if (ec) {
    status_ = Status::Failed;
    return false;
  }

  handle_ = connection_->get_handle();

  connection_->set_open_handler(websocketpp::lib::bind(
      &WebSocketTLSClient::onOpen,
      this,
      &socket_,
      websocketpp::lib::placeholders::_1));

  connection_->set_message_handler(websocketpp::lib::bind(
      &WebSocketTLSClient::onMessage,
      this,
      &socket_,
      websocketpp::lib::placeholders::_1,
      websocketpp::lib::placeholders::_2));

  connection_->set_fail_handler(websocketpp::lib::bind(
      &WebSocketTLSClient::onFail,
      this,
      &socket_,
      websocketpp::lib::placeholders::_1));

  connection_->set_close_handler(websocketpp::lib::bind(
      &WebSocketTLSClient::onClose,
      this,
      &socket_,
      websocketpp::lib::placeholders::_1));

  auto connected = connected_.get_future();

  socket_.connect(connection_);

  auto state = connected.wait_for(std::chrono::seconds(10));
  if (state == std::future_status::ready) {
    return connected.get();
  }

  disconnect();

  return false;
}

void WebSocketTLSClient::disconnect() {
  socket_.stop_perpetual();

  if (status_ == Status::Connecting || status_ == Status::Open ||
      status_ == Status::Failed) {
    websocketpp::lib::error_code ec;
    socket_.close(handle_, websocketpp::close::status::going_away, "", ec);
  }
  socket_.stop();
  status_ = Status::Closed;
  if (thread_ && thread_->joinable()) {
    thread_->join();
  }

  thread_ = nullptr;
  eventBase_->add(
      [eventHandler = eventHandler_]() { eventHandler(SocketEvent::CLOSE); });
}

void WebSocketTLSClient::send(
    const folly::dynamic& message,
    SocketSendHandler completion) {
  std::string json = folly::toJson(message);
  send(json, std::move(completion));
}

void WebSocketTLSClient::send(
    const std::string& message,
    SocketSendHandler completion) {
  websocketpp::lib::error_code ec;
  socket_.send(
      handle_,
      &message[0],
      message.size(),
      websocketpp::frame::opcode::text,
      ec);
  completion();
}

/**
    Only ever used for insecure connections to receive the device_id from a
    signCertificate request. If the intended usage ever changes, then a better
    approach needs to be put in place.
 */
void WebSocketTLSClient::sendExpectResponse(
    const std::string& message,
    SocketSendExpectResponseHandler completion) {
  connection_->set_message_handler(
      [completion, eventBase = eventBase_](
          websocketpp::connection_hdl hdl, SocketTLSClient::message_ptr msg) {
        const std::string& payload = msg->get_payload();
        eventBase->add([completion, payload] { completion(payload, false); });
      });
  websocketpp::lib::error_code ec;
  socket_.send(
      handle_,
      &message[0],
      message.size(),
      websocketpp::frame::opcode::text,
      ec);
  if (ec) {
    auto reason = ec.message();
    completion(reason, true);
  }
}

void WebSocketTLSClient::onOpen(
    SocketTLSClient* c,
    websocketpp::connection_hdl hdl) {
  if (status_ == Status::Connecting) {
    connected_.set_value(true);
  }

  status_ = Status::Initializing;
  eventBase_->add(
      [eventHandler = eventHandler_]() { eventHandler(SocketEvent::OPEN); });
}

void WebSocketTLSClient::onMessage(
    SocketTLSClient* c,
    websocketpp::connection_hdl hdl,
    SocketTLSClient::message_ptr msg) {
  const std::string& payload = msg->get_payload();
  if (messageHandler_) {
    eventBase_->add([payload, messageHandler = messageHandler_]() {
      messageHandler(payload);
    });
  }
}

void WebSocketTLSClient::onFail(
    SocketTLSClient* c,
    websocketpp::connection_hdl hdl) {
  SocketTLSClient::connection_ptr con = c->get_con_from_hdl(hdl);
  auto server = con->get_response_header("Server");
  auto reason = con->get_ec().message();
  auto sslError =
      (reason.find("TLS handshake failed") != std::string::npos ||
       reason.find("Generic TLS related error") != std::string::npos);

  if (status_ == Status::Connecting) {
    if (sslError) {
      try {
        connected_.set_exception(
            std::make_exception_ptr(folly::AsyncSocketException(
                folly::AsyncSocketException::SSL_ERROR,
                "SSL handshake failed")));
      } catch (...) {
        // set_exception() may throw an exception
        // In that case, just set the value to false.
        connected_.set_value(false);
      }
    } else {
      connected_.set_value(false);
    }
  }
  status_ = Status::Failed;
  eventBase_->add([eventHandler = eventHandler_, sslError]() {
    if (sslError) {
      eventHandler(SocketEvent::SSL_ERROR);
    } else {
      eventHandler(SocketEvent::ERROR);
    }
  });
}

void WebSocketTLSClient::onClose(
    SocketTLSClient* c,
    websocketpp::connection_hdl hdl) {
  status_ = Status::Closed;
  eventBase_->add(
      [eventHandler = eventHandler_]() { eventHandler(SocketEvent::CLOSE); });
}

SocketTLSContext WebSocketTLSClient::onTLSInit(
    const char* hostname,
    websocketpp::connection_hdl) {
  SocketTLSContext ctx =
      websocketpp::lib::make_shared<boost::asio::ssl::context>(
          boost::asio::ssl::context::sslv23);

  ctx->set_options(
      boost::asio::ssl::context::default_workarounds |
      boost::asio::ssl::context::no_sslv2 |
      boost::asio::ssl::context::no_sslv3 |
      boost::asio::ssl::context::single_dh_use);

  ctx->set_verify_mode(boost::asio::ssl::verify_peer);
  ctx->load_verify_file(connectionContextStore_->getPath(
      ConnectionContextStore::StoreItem::FLIPPER_CA));

  boost::system::error_code error;
  ctx->use_certificate_file(
      connectionContextStore_->getPath(
          ConnectionContextStore::StoreItem::CLIENT_CERT),
      boost::asio::ssl::context::pem,
      error);
  ctx->use_private_key_file(
      connectionContextStore_->getPath(
          ConnectionContextStore::StoreItem::PRIVATE_KEY),
      boost::asio::ssl::context::pem,
      error);

  return ctx;
}

} // namespace flipper
} // namespace facebook

#endif
<commit_msg>C++ WebSocket<commit_after>/*
 * Copyright (c) Meta Platforms, Inc. and affiliates.
 *
 * This source code is licensed under the MIT license found in the
 * LICENSE file in the root directory of this source tree.
 */

#ifdef FB_SONARKIT_ENABLED

#include "WebSocketTLSClient.h"
#include <Flipper/ConnectionContextStore.h>
#include <Flipper/FlipperTransportTypes.h>
#include <Flipper/FlipperURLSerializer.h>
#include <Flipper/Log.h>
#include <folly/String.h>
#include <folly/futures/Future.h>
#include <folly/io/async/AsyncSocketException.h>
#include <folly/io/async/SSLContext.h>
#include <folly/json.h>
#include <websocketpp/common/memory.hpp>
#include <websocketpp/common/thread.hpp>
#include <websocketpp/config/asio.hpp>
#include <cctype>
#include <iomanip>
#include <sstream>
#include <stdexcept>
#include <string>
#include <thread>

namespace facebook {
namespace flipper {

WebSocketTLSClient::WebSocketTLSClient(
    FlipperConnectionEndpoint endpoint,
    std::unique_ptr<FlipperSocketBasePayload> payload,
    folly::EventBase* eventBase)
    : WebSocketTLSClient(
          std::move(endpoint),
          std::move(payload),
          eventBase,
          nullptr) {}

WebSocketTLSClient::WebSocketTLSClient(
    FlipperConnectionEndpoint endpoint,
    std::unique_ptr<FlipperSocketBasePayload> payload,
    folly::EventBase* eventBase,
    ConnectionContextStore* connectionContextStore)
    : BaseClient(
          std::move(endpoint),
          std::move(payload),
          eventBase,
          connectionContextStore) {
  status_ = Status::Unconnected;

  socket_.clear_access_channels(websocketpp::log::alevel::all);
  socket_.clear_error_channels(websocketpp::log::elevel::all);
  socket_.init_asio();
  socket_.start_perpetual();

  thread_ = websocketpp::lib::make_shared<websocketpp::lib::thread>(
      &SocketTLSClient::run, &socket_);
}

WebSocketTLSClient::~WebSocketTLSClient() {
  disconnect();
}

bool WebSocketTLSClient::connect(FlipperConnectionManager* manager) {
  if (status_ != Status::Unconnected) {
    return false;
  }

  status_ = Status::Connecting;

  std::string connectionURL = endpoint_.secure ? "wss://" : "ws://";
  connectionURL += endpoint_.host;
  connectionURL += ":";
  connectionURL += std::to_string(endpoint_.port);

  auto serializer = URLSerializer{};
  payload_->serialize(serializer);
  auto payload = serializer.serialize();

  if (payload.size()) {
    connectionURL += "/?";
    connectionURL += payload;
  }

  socket_.set_tls_init_handler(bind(
      &WebSocketTLSClient::onTLSInit,
      this,
      endpoint_.host.c_str(),
      websocketpp::lib::placeholders::_1));

  auto uri = websocketpp::lib::make_shared<websocketpp::uri>(connectionURL);
  websocketpp::lib::error_code ec;
  connection_ = socket_.get_connection(uri, ec);

  if (ec) {
    status_ = Status::Failed;
    return false;
  }

  handle_ = connection_->get_handle();

  connection_->set_open_handler(websocketpp::lib::bind(
      &WebSocketTLSClient::onOpen,
      this,
      &socket_,
      websocketpp::lib::placeholders::_1));

  connection_->set_message_handler(websocketpp::lib::bind(
      &WebSocketTLSClient::onMessage,
      this,
      &socket_,
      websocketpp::lib::placeholders::_1,
      websocketpp::lib::placeholders::_2));

  connection_->set_fail_handler(websocketpp::lib::bind(
      &WebSocketTLSClient::onFail,
      this,
      &socket_,
      websocketpp::lib::placeholders::_1));

  connection_->set_close_handler(websocketpp::lib::bind(
      &WebSocketTLSClient::onClose,
      this,
      &socket_,
      websocketpp::lib::placeholders::_1));

  auto connected = connected_.get_future();

  socket_.connect(connection_);

  auto state = connected.wait_for(std::chrono::seconds(10));
  if (state == std::future_status::ready) {
    return connected.get();
  }

  disconnect();

  return false;
}

void WebSocketTLSClient::disconnect() {
  socket_.stop_perpetual();

  if (status_ == Status::Connecting || status_ == Status::Open ||
      status_ == Status::Failed) {
    websocketpp::lib::error_code ec;
    socket_.close(handle_, websocketpp::close::status::going_away, "", ec);
  }
  socket_.stop();
  status_ = Status::Closed;
  if (thread_ && thread_->joinable()) {
    thread_->join();
  }

  thread_ = nullptr;
  eventBase_->add(
      [eventHandler = eventHandler_]() { eventHandler(SocketEvent::CLOSE); });
}

void WebSocketTLSClient::send(
    const folly::dynamic& message,
    SocketSendHandler completion) {
  std::string json = folly::toJson(message);
  send(json, std::move(completion));
}

void WebSocketTLSClient::send(
    const std::string& message,
    SocketSendHandler completion) {
  websocketpp::lib::error_code ec;
  socket_.send(
      handle_,
      &message[0],
      message.size(),
      websocketpp::frame::opcode::text,
      ec);
  completion();
}

/**
    Only ever used for insecure connections to receive the device_id from a
    signCertificate request. If the intended usage ever changes, then a better
    approach needs to be put in place.
 */
void WebSocketTLSClient::sendExpectResponse(
    const std::string& message,
    SocketSendExpectResponseHandler completion) {
  connection_->set_message_handler(
      [completion, eventBase = eventBase_](
          websocketpp::connection_hdl hdl, SocketTLSClient::message_ptr msg) {
        const std::string& payload = msg->get_payload();
        eventBase->add([completion, payload] { completion(payload, false); });
      });
  websocketpp::lib::error_code ec;
  socket_.send(
      handle_,
      &message[0],
      message.size(),
      websocketpp::frame::opcode::text,
      ec);
  if (ec) {
    auto reason = ec.message();
    completion(reason, true);
  }
}

void WebSocketTLSClient::onOpen(
    SocketTLSClient* c,
    websocketpp::connection_hdl hdl) {
  if (status_ == Status::Connecting) {
    connected_.set_value(true);
  }

  status_ = Status::Initializing;
  eventBase_->add(
      [eventHandler = eventHandler_]() { eventHandler(SocketEvent::OPEN); });
}

void WebSocketTLSClient::onMessage(
    SocketTLSClient* c,
    websocketpp::connection_hdl hdl,
    SocketTLSClient::message_ptr msg) {
  const std::string& payload = msg->get_payload();
  if (messageHandler_) {
    eventBase_->add([payload, messageHandler = messageHandler_]() {
      messageHandler(payload);
    });
  }
}

void WebSocketTLSClient::onFail(
    SocketTLSClient* c,
    websocketpp::connection_hdl hdl) {
  SocketTLSClient::connection_ptr con = c->get_con_from_hdl(hdl);
  auto server = con->get_response_header("Server");
  auto reason = con->get_ec().message();
  auto sslError =
      (reason.find("TLS handshake failed") != std::string::npos ||
       reason.find("Generic TLS related error") != std::string::npos);

  if (status_ == Status::Connecting) {
    if (sslError) {
      try {
        connected_.set_exception(
            std::make_exception_ptr(folly::AsyncSocketException(
                folly::AsyncSocketException::SSL_ERROR,
                "SSL handshake failed")));
      } catch (...) {
        // set_exception() may throw an exception
        // In that case, just set the value to false.
        connected_.set_value(false);
      }
    } else {
      connected_.set_value(false);
    }
  }
  status_ = Status::Failed;
  eventBase_->add([eventHandler = eventHandler_, sslError]() {
    if (sslError) {
      eventHandler(SocketEvent::SSL_ERROR);
    } else {
      eventHandler(SocketEvent::ERROR);
    }
  });
}

void WebSocketTLSClient::onClose(
    SocketTLSClient* c,
    websocketpp::connection_hdl hdl) {
  status_ = Status::Closed;
  eventBase_->add(
      [eventHandler = eventHandler_]() { eventHandler(SocketEvent::CLOSE); });
}

SocketTLSContext WebSocketTLSClient::onTLSInit(
    const char* hostname,
    websocketpp::connection_hdl) {
  namespace asio = websocketpp::lib::asio;
  SocketTLSContext ctx = websocketpp::lib::make_shared<asio::ssl::context>(
      asio::ssl::context::sslv23);

  ctx->set_options(
      asio::ssl::context::default_workarounds | asio::ssl::context::no_sslv2 |
      asio::ssl::context::no_sslv3 | asio::ssl::context::single_dh_use);

  ctx->set_verify_mode(asio::ssl::verify_peer);
  ctx->load_verify_file(connectionContextStore_->getPath(
      ConnectionContextStore::StoreItem::FLIPPER_CA));

  asio::error_code error;
  ctx->use_certificate_file(
      connectionContextStore_->getPath(
          ConnectionContextStore::StoreItem::CLIENT_CERT),
      asio::ssl::context::pem,
      error);
  ctx->use_private_key_file(
      connectionContextStore_->getPath(
          ConnectionContextStore::StoreItem::PRIVATE_KEY),
      asio::ssl::context::pem,
      error);

  return ctx;
}

} // namespace flipper
} // namespace facebook

#endif
<|endoftext|>


<commit_before>/*!
 * \file
 * Defines a key/value storage class with a hash table backend.
 *
 * \author Andres Jaan Tack <andres.jaan.tack@eesti.ee>
 */
#include <boost/thread/future.hpp>
#include <memory>
#include <stdexcept>

/*!
 * This key value storage may be thought of as a simple hash table, only accessible by key, with one primary
 * exception: Assignments to this hash table return immediately, but resolve asynchronously to a future value.
 * You may, for instance, block on a write to this hash table, and thus be sure the value was delivered:
 *
 *    storage s;
 *    auto result = s["breakfast"].set("ham and eggs");
 *    result.wait();
 *    if (result.has_value())
 *        assert(*s["breakfast"] == "ham and eggs")
 *    else
 *        cerr << "Write failed!" << endl;
 *
 * You may also "fire and forget" the write, by eliding everything after set(). A failure will be logged by
 * the implementation, but it will not invalidate future accesses of any keys in s.
 */
class storage
{
  public:
    typedef std::string key;
    typedef std::string value;

    /*! \post the table is empty. */
    storage ();
    ~storage ();

    /*! An exception type indicating that an assigment at a key has failed. */
    class failed_assignment;

    /*! A return type for accessors which may be able to respond, "no item here." */
    class optional_value;

    /*!
     * Returns the value mapped by the given key. May return a value evaluating to "false", in which case
     * there was no value at this key. The value returned is directly assignable, so storage["foo"] = "bar"
     * constitutes setting the value at "foo" to "bar", irrespective of any previous values present.
     */
    optional_value& operator[] (const key&);
    const optional_value& operator[] (const key&) const;

  private:
    class implementation;
    std::unique_ptr<implementation> pimpl_;
};

class storage::optional_value
{
  private:
    class implementation;

  protected:
    friend class storage;
    optional_value (const storage::key& k);
    optional_value (std::shared_ptr<implementation>& p)
      : pimpl_(p)
    {   }

  public:
    /*! Begins an asynchronous assignment to the value keyed here. */
    boost::shared_future<std::unique_ptr<optional_value>> set (const storage::value& v);

    /*! \returns True iff a value exists here. False means "no value". */
    operator bool () const;

    /*!
     * \pre this object must evaluate to true.
     * \returns The value present in this key location.
     */
    const storage::value& operator* () const  { return value(); }
    const storage::value& operator-> () const { return value(); }
    const storage::value& value () const;

  private:
    std::shared_ptr<implementation> pimpl_;  /*!< The single concrete value referred to by all copies by a particular key. */
};

struct storage::failed_assignment
      : public std::exception
{
    failed_assignment (const std::string& key, const std::string& value)
      : key(key),
        value(value)
    {   }

    ~failed_assignment () throw()
    {   }

    virtual const char* what () const throw();

    const std::string key;
    const std::string value;
};
<commit_msg>Removed dead code.<commit_after>/*!
 * \file
 * Defines a key/value storage class with a hash table backend.
 *
 * \author Andres Jaan Tack <andres.jaan.tack@eesti.ee>
 */
#include <boost/thread/future.hpp>
#include <memory>
#include <stdexcept>

/*!
 * This key value storage may be thought of as a simple hash table, only accessible by key, with one primary
 * exception: Assignments to this hash table return immediately, but resolve asynchronously to a future value.
 * You may, for instance, block on a write to this hash table, and thus be sure the value was delivered:
 *
 *    storage s;
 *    auto result = s["breakfast"].set("ham and eggs");
 *    result.wait();
 *    if (result.has_value())
 *        assert(*s["breakfast"] == "ham and eggs")
 *    else
 *        cerr << "Write failed!" << endl;
 *
 * You may also "fire and forget" the write, by eliding everything after set(). A failure will be logged by
 * the implementation, but it will not invalidate future accesses of any keys in s.
 */
class storage
{
  public:
    typedef std::string key;
    typedef std::string value;

    /*! \post the table is empty. */
    storage ();
    ~storage ();

    /*! A return type for accessors which may be able to respond, "no item here." */
    class optional_value;

    /*!
     * Returns the value mapped by the given key. May return a value evaluating to "false", in which case
     * there was no value at this key. The value returned is directly assignable, so storage["foo"] = "bar"
     * constitutes setting the value at "foo" to "bar", irrespective of any previous values present.
     */
    optional_value& operator[] (const key&);
    const optional_value& operator[] (const key&) const;

  private:
    class implementation;
    std::unique_ptr<implementation> pimpl_;
};

class storage::optional_value
{
  private:
    class implementation;

  protected:
    friend class storage;
    optional_value (const storage::key& k);
    optional_value (std::shared_ptr<implementation>& p)
      : pimpl_(p)
    {   }

  public:
    /*! Begins an asynchronous assignment to the value keyed here. */
    boost::shared_future<std::unique_ptr<optional_value>> set (const storage::value& v);

    /*! \returns True iff a value exists here. False means "no value". */
    operator bool () const;

    /*!
     * \pre this object must evaluate to true.
     * \returns The value present in this key location.
     */
    const storage::value& operator* () const  { return value(); }
    const storage::value& operator-> () const { return value(); }
    const storage::value& value () const;

  private:
    std::shared_ptr<implementation> pimpl_;  /*!< The single concrete value referred to by all copies by a particular key. */
};
<|endoftext|>


<commit_before>/* -*- Mode: C++; tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*- */
/*
 *     Copyright 2012 Couchbase, Inc.
 *
 *   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 "config.h"
#include "ep_time.h"
#include <stdlib.h>

static rel_time_t uninitialized_current_time(void) {
    abort();
    return 0;
}

static time_t default_abs_time(rel_time_t notused) {
    (void)notused;
    abort();
    return 0;
}

static rel_time_t default_reltime(time_t notused) {
    (void)notused;
    abort();
    return 0;
}

void initialize_time_functions(const SERVER_CORE_API* core_api) {
    if (ep_current_time == uninitialized_current_time) {
        ep_current_time = core_api->get_current_time;
    }
    if (ep_abs_time == default_abs_time) {
        ep_abs_time = core_api->abstime;
    }
    if (ep_reltime == default_reltime) {
        ep_reltime = core_api->realtime;
    }
}

rel_time_t (*ep_current_time)(void) = uninitialized_current_time;
time_t (*ep_abs_time)(rel_time_t) = default_abs_time;
rel_time_t (*ep_reltime)(time_t) = default_reltime;

time_t ep_real_time(void) {
    return ep_abs_time(ep_current_time());
}
<commit_msg>MB-21540: ep_time.cc: Replace abort() with std::logic_error<commit_after>/* -*- Mode: C++; tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*- */
/*
 *     Copyright 2012 Couchbase, Inc.
 *
 *   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 "config.h"

#include "ep_time.h"

#include <stdexcept>

static rel_time_t uninitialized_current_time(void) {
    throw std::logic_error("unitialized_current_time called");
    return 0;
}

static time_t default_abs_time(rel_time_t notused) {
    throw std::logic_error("default_abs_time called");
    return 0;
}

static rel_time_t default_reltime(time_t notused) {
    throw std::logic_error("default_reltime called");
    return 0;
}

void initialize_time_functions(const SERVER_CORE_API* core_api) {
    if (ep_current_time == uninitialized_current_time) {
        ep_current_time = core_api->get_current_time;
    }
    if (ep_abs_time == default_abs_time) {
        ep_abs_time = core_api->abstime;
    }
    if (ep_reltime == default_reltime) {
        ep_reltime = core_api->realtime;
    }
}

rel_time_t (*ep_current_time)(void) = uninitialized_current_time;
time_t (*ep_abs_time)(rel_time_t) = default_abs_time;
rel_time_t (*ep_reltime)(time_t) = default_reltime;

time_t ep_real_time(void) {
    return ep_abs_time(ep_current_time());
}
<|endoftext|>


<commit_before>/*
 * Error document handler.
 *
 * author: Max Kellermann <mk@cm4all.com>
 */

#include "errdoc.hxx"
#include "request.hxx"
#include "bp_instance.hxx"
#include "http_server/Request.hxx"
#include "http_headers.hxx"
#include "http_response.hxx"
#include "tcache.hxx"
#include "TranslateHandler.hxx"
#include "ResourceLoader.hxx"
#include "http_response.hxx"
#include "istream/istream.hxx"
#include "istream/istream_hold.hxx"

#include <glib.h>

#include <daemon/log.h>

struct error_response {
    struct async_operation operation;
    struct async_operation_ref async_ref;

    Request *request2;

    http_status_t status;
    HttpHeaders headers;
    Istream *body;

    TranslateRequest translate_request;
};

static void
errdoc_resubmit(error_response &er)
{
    response_dispatch(*er.request2, er.status, std::move(er.headers), er.body);
}

/*
 * HTTP response handler
 *
 */

static void
errdoc_response_response(http_status_t status, StringMap &&headers,
                         Istream *body, void *ctx)
{
    error_response &er = *(error_response *)ctx;

    if (http_status_is_success(status)) {
        if (er.body != nullptr)
            /* close the original (error) response body */
            er.body->CloseUnused();

        response_handler.InvokeResponse(er.request2, er.status,
                                        std::move(headers), body);
    } else {
        if (body != nullptr)
            /* discard the error document response */
            er.body->CloseUnused();

        errdoc_resubmit(er);
    }
}

static void
errdoc_response_abort(GError *error, void *ctx)
{
    error_response &er = *(error_response *)ctx;

    daemon_log(2, "error on error document of %s: %s\n",
               er.request2->request.uri, error->message);
    g_error_free(error);

    errdoc_resubmit(er);
}

const struct http_response_handler errdoc_response_handler = {
    .response = errdoc_response_response,
    .abort = errdoc_response_abort,
};

/*
 * translate handler
 *
 */

static void
errdoc_translate_response(TranslateResponse &response, void *ctx)
{
    error_response &er = *(error_response *)ctx;

    if ((response.status == (http_status_t)0 ||
         http_status_is_success(response.status)) &&
        response.address.IsDefined()) {
        Request *request2 = er.request2;
        auto *instance = &request2->instance;

        instance->cached_resource_loader
            ->SendRequest(request2->pool, 0, HTTP_METHOD_GET,
                          response.address, HTTP_STATUS_OK,
                          StringMap(request2->pool), nullptr, nullptr,
                          errdoc_response_handler, &er,
                          request2->async_ref);
    } else
        errdoc_resubmit(er);
}

static void
errdoc_translate_error(GError *error, void *ctx)
{
    error_response &er = *(error_response *)ctx;

    daemon_log(2, "error document translation error: %s\n", error->message);
    g_error_free(error);

    errdoc_resubmit(er);
}

static const TranslateHandler errdoc_translate_handler = {
    .response = errdoc_translate_response,
    .error = errdoc_translate_error,
};

static void
fill_translate_request(TranslateRequest *t,
                       const TranslateRequest *src,
                       ConstBuffer<void> error_document,
                       http_status_t status)
{
    *t = *src;
    t->error_document = error_document;
    t->error_document_status = status;
}

/*
 * async operation
 *
 */

static void
errdoc_abort(struct async_operation *ao)
{
    error_response &er = *(error_response *)ao;

    if (er.body != nullptr)
        er.body->CloseUnused();

    er.async_ref.Abort();
}

static const struct async_operation_class errdoc_operation = {
    .abort = errdoc_abort,
};

/*
 * constructor
 *
 */

void
errdoc_dispatch_response(Request &request2, http_status_t status,
                         ConstBuffer<void> error_document,
                         HttpHeaders &&headers, Istream *body)
{
    assert(!error_document.IsNull());

    auto *instance = &request2.instance;

    assert(instance->translate_cache != nullptr);

    error_response *er = NewFromPool<error_response>(request2.pool);
    er->request2 = &request2;
    er->status = status;
    er->headers = std::move(headers);
    er->body = body != nullptr
        ? istream_hold_new(request2.pool, *body)
        : nullptr;

    er->operation.Init(errdoc_operation);
    request2.async_ref.Set(er->operation);

    fill_translate_request(&er->translate_request,
                           &request2.translate.request,
                           error_document, status);
    translate_cache(request2.pool, *instance->translate_cache,
                    er->translate_request,
                    errdoc_translate_handler, er,
                    er->async_ref);
}
<commit_msg>errdoc: use CamelCase<commit_after>/*
 * Error document handler.
 *
 * author: Max Kellermann <mk@cm4all.com>
 */

#include "errdoc.hxx"
#include "request.hxx"
#include "bp_instance.hxx"
#include "http_server/Request.hxx"
#include "http_headers.hxx"
#include "http_response.hxx"
#include "tcache.hxx"
#include "TranslateHandler.hxx"
#include "ResourceLoader.hxx"
#include "http_response.hxx"
#include "istream/istream.hxx"
#include "istream/istream_hold.hxx"

#include <glib.h>

#include <daemon/log.h>

struct ErrorResponseLoader {
    struct async_operation operation;
    struct async_operation_ref async_ref;

    Request *request2;

    http_status_t status;
    HttpHeaders headers;
    Istream *body;

    TranslateRequest translate_request;
};

static void
errdoc_resubmit(ErrorResponseLoader &er)
{
    response_dispatch(*er.request2, er.status, std::move(er.headers), er.body);
}

/*
 * HTTP response handler
 *
 */

static void
errdoc_response_response(http_status_t status, StringMap &&headers,
                         Istream *body, void *ctx)
{
    auto &er = *(ErrorResponseLoader *)ctx;

    if (http_status_is_success(status)) {
        if (er.body != nullptr)
            /* close the original (error) response body */
            er.body->CloseUnused();

        response_handler.InvokeResponse(er.request2, er.status,
                                        std::move(headers), body);
    } else {
        if (body != nullptr)
            /* discard the error document response */
            er.body->CloseUnused();

        errdoc_resubmit(er);
    }
}

static void
errdoc_response_abort(GError *error, void *ctx)
{
    auto &er = *(ErrorResponseLoader *)ctx;

    daemon_log(2, "error on error document of %s: %s\n",
               er.request2->request.uri, error->message);
    g_error_free(error);

    errdoc_resubmit(er);
}

const struct http_response_handler errdoc_response_handler = {
    .response = errdoc_response_response,
    .abort = errdoc_response_abort,
};

/*
 * translate handler
 *
 */

static void
errdoc_translate_response(TranslateResponse &response, void *ctx)
{
    auto &er = *(ErrorResponseLoader *)ctx;

    if ((response.status == (http_status_t)0 ||
         http_status_is_success(response.status)) &&
        response.address.IsDefined()) {
        Request *request2 = er.request2;
        auto *instance = &request2->instance;

        instance->cached_resource_loader
            ->SendRequest(request2->pool, 0, HTTP_METHOD_GET,
                          response.address, HTTP_STATUS_OK,
                          StringMap(request2->pool), nullptr, nullptr,
                          errdoc_response_handler, &er,
                          request2->async_ref);
    } else
        errdoc_resubmit(er);
}

static void
errdoc_translate_error(GError *error, void *ctx)
{
    auto &er = *(ErrorResponseLoader *)ctx;

    daemon_log(2, "error document translation error: %s\n", error->message);
    g_error_free(error);

    errdoc_resubmit(er);
}

static const TranslateHandler errdoc_translate_handler = {
    .response = errdoc_translate_response,
    .error = errdoc_translate_error,
};

static void
fill_translate_request(TranslateRequest *t,
                       const TranslateRequest *src,
                       ConstBuffer<void> error_document,
                       http_status_t status)
{
    *t = *src;
    t->error_document = error_document;
    t->error_document_status = status;
}

/*
 * async operation
 *
 */

static void
errdoc_abort(struct async_operation *ao)
{
    auto &er = *(ErrorResponseLoader *)ao;

    if (er.body != nullptr)
        er.body->CloseUnused();

    er.async_ref.Abort();
}

static const struct async_operation_class errdoc_operation = {
    .abort = errdoc_abort,
};

/*
 * constructor
 *
 */

void
errdoc_dispatch_response(Request &request2, http_status_t status,
                         ConstBuffer<void> error_document,
                         HttpHeaders &&headers, Istream *body)
{
    assert(!error_document.IsNull());

    auto *instance = &request2.instance;

    assert(instance->translate_cache != nullptr);

    auto *er = NewFromPool<ErrorResponseLoader>(request2.pool);
    er->request2 = &request2;
    er->status = status;
    er->headers = std::move(headers);
    er->body = body != nullptr
        ? istream_hold_new(request2.pool, *body)
        : nullptr;

    er->operation.Init(errdoc_operation);
    request2.async_ref.Set(er->operation);

    fill_translate_request(&er->translate_request,
                           &request2.translate.request,
                           error_document, status);
    translate_cache(request2.pool, *instance->translate_cache,
                    er->translate_request,
                    errdoc_translate_handler, er,
                    er->async_ref);
}
<|endoftext|>


<commit_before>/*
 * =========================================================================================
 * Name        : eventLib.cpp
 * Author      : Duc Dung Nguyen
 * Email       : nddung@hcmut.edu.vn
 * Copyright   : Faculty of Computer Science and Engineering - Bach Khoa University
 * Description : library for Assignment 1 - Data structures and Algorithms - Spring 2017
 *               This library contains functions used for event management
 * =========================================================================================
 */

#include "eventLib.h"

/// NOTE: each event will be separated by spaces, or endline character
void loadEvents(char* fName, L1List<busEvent_t> &eList) {
    ifstream inFile(fName);

    if (inFile) {
        string line;
        while (getline(inFile , line)) {
            istringstream iss(line);
            while (iss) {
                string sub;
                iss >> sub;
                busEvent_t __e(sub);
                eList.insertHead(__e);
            }
        }
        eList.reverse();
        inFile.close();
    }
    else {
        cout << "The file is not found!";
    }
}
<commit_msg>Fix endline character problem on Windows<commit_after>/*
 * =========================================================================================
 * Name        : eventLib.cpp
 * Author      : Duc Dung Nguyen
 * Email       : nddung@hcmut.edu.vn
 * Copyright   : Faculty of Computer Science and Engineering - Bach Khoa University
 * Description : library for Assignment 1 - Data structures and Algorithms - Spring 2017
 *               This library contains functions used for event management
 * =========================================================================================
 */

#include "eventLib.h"

/// NOTE: each event will be separated by spaces, or endline character
void loadEvents(char* fName, L1List<busEvent_t> &eList) {
    ifstream inFile(fName);

    if (inFile) {
        string line;
        while (getline(inFile , line)) {
            /// On Windows, lines on file ends with \r\n. So you have to remove \r
            if (line[line.length() - 1] == '\r')
                line.erase(line.length() - 1);

            istringstream iss(line);
            while (iss) {
                string sub;
                iss >> sub;
                busEvent_t __e(sub);
                eList.insertHead(__e);
            }
        }
        eList.reverse();
        inFile.close();
    }
    else {
        cout << "The file is not found!";
    }
}
<|endoftext|>


<commit_before>#include <iostream>
#include <vector>

using namespace std;

#define forn(i,n) for(int i=0;i<(int)(n);i++)
#define forsn(i,s,n) for(int i=(s);i<(int)(n);i++)
#define dforn(i,n) for(int i=(n)-1;i>=0;i--)
#define dforsn(i,s,n) for(int i=(n)-1;i>=(int)(s);i--)

#include "SegmentTree.h"

// Codigos de nodos, no irian al notebook.

// Ejemplo complejo: Problema D Round 2, Hacker Cup 2015
// INICIO DE CODIGO DEL SEGMENT_TREE_HACKERCUP

typedef long long tint;
const tint MODU = 1000000000;

struct HackerCupUpdateData
{
    tint val; // Poner este valor, -1 para no hacer nada
    tint C,D; // Coeficientes de la lineal
    HackerCupUpdateData() : val(-1), C(0), D(0) {}
    void update(int i, int j, const HackerCupUpdateData& data)
    {
        if (data.val != -1)
        {
            val = data.val;
            C = 0;
            D = 0;
        }
        C += data.C;
        D += data.D;
    }
};

tint oddInRange(tint a,tint b)
{
    return (b-a)/2 + ((a%2) * (1 - (b%2)) );
}

tint evenInRange(tint a,tint b)
{
    return b - a - oddInRange(a,b);
}

tint integral(tint i, tint j)
{
    return ((j * (j-1) - i * (i-1)) / 2) % MODU;
}

struct HackerCupStat
{
    // Statistics
    tint sum;
    tint oddAtEven, oddAtOdd; // Cantidad de impares en posiciones pares / impares.

    HackerCupStat() : sum(0), oddAtEven(0), oddAtOdd(0) {}
    HackerCupStat(const HackerCupStat& a, const HackerCupStat& b)
    {
        oddAtEven = a.oddAtEven + b.oddAtEven;
        oddAtOdd  = a.oddAtOdd + b.oddAtOdd;
        sum = (a.sum + b.sum) % MODU;
    }
    void update(int i, int j, const HackerCupUpdateData& data)
    {
        if (data.val != -1)
        {
            sum = ((j-i) * data.val) % MODU;
            oddAtEven = evenInRange(i,j) * (data.val % 2);
            oddAtOdd = oddInRange(i,j) * (data.val % 2);
        }
        sum += data.C * (j-i);
        sum %= MODU;
        sum += data.D * integral(i, j);
        sum %= MODU;
        if (data.C % 2)
        {
            oddAtEven = evenInRange(i,j) - oddAtEven;
            oddAtOdd  = oddInRange(i,j) - oddAtOdd;
        }
        if (data.D % 2)
        {
            oddAtOdd  = oddInRange(i,j) - oddAtOdd;
        }
    }
};

// FIN DE CODIGO DEL SEGMENT_TREE_HACKERCUP

// Nuevo ejemplo bien cortito: Esto seria todo lo que hay que agregar al codigo de notebook para un lazy-update con suma.
// Notar que el codigo de esto es el mismo usemos lazy-update o no: Si no vamos a necesitar lazy update, se pueden comentar
// varias lineas en la implementacion del segment tree, y no haria falta la operacion update de SumData, ni el constructor default del mismo.
// Con lo cual en ese caso podriamos usar de sumData directamente a un int, lo cual es comodo porque ni hay que programar este structcito.

struct SumUpdateData
{
    int lazy;
    SumUpdateData() : lazy(0) {}
    SumUpdateData(int val) : lazy(val) {}
    void update(int i,int j, const SumUpdateData &o) {lazy += o.lazy;};
};

struct SumStat
{
    int s;
    SumStat() : s(0) {}
    SumStat(int val) : s(val) {}
    SumStat(const SumStat &a, const SumStat &b) : s(a.s + b.s) {}
    void update(int i,int j, const SumUpdateData &data) {s += data.lazy * (j-i);}
};

// Ejemplo de uso.

void ejemploSumaConLazyUpdate()
{
    // Notar que al haberle puesto un constructor que toma int a LazySumStat y LazySumData, podemos asignarle ints de una,
    //  lo cual nos limpia un poco la sintaxis en este ejemplo pavo donde los structs no son nada mas que un int.
    int N = 10;
    SegmentTree<SumStat, SumUpdateData>::Node *v;
    SegmentTree<SumStat, SumUpdateData> tree(N, v); // En esta version, todo bien con la memoria local de stack
    forn(i,N) v[i].stat = i*i; // Se inicializa el v[i].stat, y los datos lazy se dejan como estan.
    tree.init();
    // Impresion del estado interno completo, a modo de DEBUG de que se construyo bien.
    forn(i,tree.N*2)
        cout << i << "   " << tree.v[i].stat.s << " " << tree.v[i].lazy.lazy << endl;

    cout << tree.get(2,5).s << endl;
    cout << tree.get(2,5).s << endl;
    tree.update(2,77);
    cout << tree.get(2,5).s << endl;
    cout << tree.get(2,5).s << endl;
    tree.updateRange(2,4,1);
    cout << tree.get(2,5).s << endl;
    cout << tree.get(2,5).s << endl;
    // Impresion del estado interno completo, a modo de DEBUG de que quedo lo que tenia que quedar.
    forn(i,tree.N*2)
        cout << i << "   " << tree.v[i].stat.s << " " << tree.v[i].lazy.lazy << endl;
}

void ejemploSumaComunSinLazyUpdate()
{
    // Notar que al haberle puesto un constructor que toma int a LazySumStat y LazySumData, podemos asignarle ints de una,
    //  lo cual nos limpia un poco la sintaxis en este ejemplo pavo donde los structs no son nada mas que un int.
    int N = 10;
    SegmentTree<SumStat, int>::Node *v;
    SegmentTree<SumStat, int> tree(N, v); // En esta version, todo bien con la memoria local de stack
    forn(i,N) v[i].stat = i*i; // Se inicializa el v[i].stat, y los datos lazy se dejan como estan.
    tree.init();
    // Impresion del estado interno completo, a modo de DEBUG de que se construyo bien.
    forn(i,tree.N*2)
        cout << i << "   " << tree.v[i].stat.s << endl;

    cout << tree.get(2,5).s << endl;
    cout << tree.get(2,5).s << endl;
    tree.update(2,77);
    cout << tree.get(2,5).s << endl;
    cout << tree.get(2,5).s << endl;
    tree.update(3,10);
    cout << tree.get(2,5).s << endl;
    cout << tree.get(2,5).s << endl;
    // Impresion del estado interno completo, a modo de DEBUG de que quedo lo que tenia que quedar.
    forn(i,tree.N*2)
        cout << i << "   " << tree.v[i].stat.s << endl;
}

int main()
{
    ejemploSumaComunSinLazyUpdate(); // Para que compile este, hay que comentar las lineas correspondientes en el codigo de SegmentTree
    ejemploSumaConLazyUpdate();
    return 0;
}
<commit_msg>Fixed examples<commit_after>#include <iostream>
#include <vector>

using namespace std;

#define forn(i,n) for(int i=0;i<(int)(n);i++)
#define forsn(i,s,n) for(int i=(s);i<(int)(n);i++)
#define dforn(i,n) for(int i=(n)-1;i>=0;i--)
#define dforsn(i,s,n) for(int i=(n)-1;i>=(int)(s);i--)

#include "SegmentTree.h"

// Codigos de nodos, no irian al notebook.

// Ejemplo complejo: Problema D Round 2, Hacker Cup 2015
// INICIO DE CODIGO DEL SEGMENT_TREE_HACKERCUP

typedef long long tint;
const tint MODU = 1000000000;

struct HackerCupUpdateData
{
    tint val; // Poner este valor, -1 para no hacer nada
    tint C,D; // Coeficientes de la lineal
    HackerCupUpdateData() : val(-1), C(0), D(0) {}
    void update(int i, int j, const HackerCupUpdateData& data)
    {
        if (data.val != -1)
        {
            val = data.val;
            C = 0;
            D = 0;
        }
        C += data.C;
        D += data.D;
    }
};

tint oddInRange(tint a,tint b)
{
    return (b-a)/2 + ((a%2) * (1 - (b%2)) );
}

tint evenInRange(tint a,tint b)
{
    return b - a - oddInRange(a,b);
}

tint integral(tint i, tint j)
{
    return ((j * (j-1) - i * (i-1)) / 2) % MODU;
}

struct HackerCupStat
{
    // Statistics
    tint sum;
    tint oddAtEven, oddAtOdd; // Cantidad de impares en posiciones pares / impares.

    HackerCupStat() : sum(0), oddAtEven(0), oddAtOdd(0) {}
    HackerCupStat(const HackerCupStat& a, const HackerCupStat& b)
    {
        oddAtEven = a.oddAtEven + b.oddAtEven;
        oddAtOdd  = a.oddAtOdd + b.oddAtOdd;
        sum = (a.sum + b.sum) % MODU;
    }
    void update(int i, int j, const HackerCupUpdateData& data)
    {
        if (data.val != -1)
        {
            sum = ((j-i) * data.val) % MODU;
            oddAtEven = evenInRange(i,j) * (data.val % 2);
            oddAtOdd = oddInRange(i,j) * (data.val % 2);
        }
        sum += data.C * (j-i);
        sum %= MODU;
        sum += data.D * integral(i, j);
        sum %= MODU;
        if (data.C % 2)
        {
            oddAtEven = evenInRange(i,j) - oddAtEven;
            oddAtOdd  = oddInRange(i,j) - oddAtOdd;
        }
        if (data.D % 2)
        {
            oddAtOdd  = oddInRange(i,j) - oddAtOdd;
        }
    }
};

// FIN DE CODIGO DEL SEGMENT_TREE_HACKERCUP

// Nuevo ejemplo bien cortito: Esto seria todo lo que hay que agregar al codigo de notebook para un lazy-update con suma.
// Notar que el codigo de esto es el mismo usemos lazy-update o no: Si no vamos a necesitar lazy update, se pueden comentar
// varias lineas en la implementacion del segment tree, y no haria falta la operacion update de SumData, ni el constructor default del mismo.
// Con lo cual en ese caso podriamos usar de sumData directamente a un int, lo cual es comodo porque ni hay que programar este structcito.

struct SumData
{
    int lazy;
    SumData() : lazy(0) {}
    SumData(int val) : lazy(val) {}
    void update(int i,int j, const SumData &o) {lazy += o.lazy;}; // Esta solo hace falta cuando usamos Lazy Update
};

struct SumStat
{
    int s;
    SumStat() : s(0) {}
    SumStat(int val) : s(val) {}
    SumStat(const SumStat &a, const SumStat &b) {merge(a,b);}
    void merge(const SumStat &a, const SumStat &b, const SumData &data = 0) {
        s = a.s + b.s;
    }
    void update(int i,int j, const SumData &data) {s += data.lazy * (j-i);} // Podria ser simplemente s += data.lazy si no usamos lazyUpdate, ya que en ese caso j-i == 1 siempre.
};

// Ejemplo de uso.

void ejemploSumaConLazyUpdate()
{
    // Notar que al haberle puesto un constructor que toma int a LazySumStat y LazySumData, podemos asignarle ints de una,
    //  lo cual nos limpia un poco la sintaxis en este ejemplo pavo donde los structs no son nada mas que un int.
    int N = 10;
    SegmentTree<SumStat, SumData>::Node *v;
    SegmentTree<SumStat, SumData> tree(N, v); // En esta version, todo bien con la memoria local de stack
    forn(i,N) v[i].stat = i*i; // Se inicializa el v[i].stat, y los datos lazy se dejan como estan.
    tree.init();
    // Impresion del estado interno completo, a modo de DEBUG de que se construyo bien.
    forn(i,tree.N*2)
        cout << i << "   " << tree.v[i].stat.s << " " << tree.v[i].lazy.lazy << endl;

    cout << tree.get(2,5).s << endl;
    cout << tree.get(2,5).s << endl;
    tree.update(2,77);
    cout << tree.get(2,5).s << endl;
    cout << tree.get(2,5).s << endl;
    tree.updateRange(2,4,1);
    cout << tree.get(2,5).s << endl;
    cout << tree.get(2,5).s << endl;
    // Impresion del estado interno completo, a modo de DEBUG de que quedo lo que tenia que quedar.
    forn(i,tree.N*2)
        cout << i << "   " << tree.v[i].stat.s << " " << tree.v[i].lazy.lazy << endl;
}

// Para que compile este, hay que comentar las lineas correspondientes en el codigo de SegmentTree

/*
void ejemploSumaComunSinLazyUpdate()
{
    // Notar que al haberle puesto un constructor que toma int a LazySumStat y LazySumData, podemos asignarle ints de una,
    //  lo cual nos limpia un poco la sintaxis en este ejemplo pavo donde los structs no son nada mas que un int.
    int N = 10;
    SegmentTree<SumStat, int>::Node *v;
    SegmentTree<SumStat, int> tree(N, v); // En esta version, todo bien con la memoria local de stack
    forn(i,N) v[i].stat = i*i; // Se inicializa el v[i].stat, y los datos lazy se dejan como estan.
    tree.init();
    // Impresion del estado interno completo, a modo de DEBUG de que se construyo bien.
    forn(i,tree.N*2)
        cout << i << "   " << tree.v[i].stat.s << endl;

    cout << tree.get(2,5).s << endl;
    cout << tree.get(2,5).s << endl;
    tree.update(2,77);
    cout << tree.get(2,5).s << endl;
    cout << tree.get(2,5).s << endl;
    tree.update(3,10);
    cout << tree.get(2,5).s << endl;
    cout << tree.get(2,5).s << endl;
    // Impresion del estado interno completo, a modo de DEBUG de que quedo lo que tenia que quedar.
    forn(i,tree.N*2)
        cout << i << "   " << tree.v[i].stat.s << endl;
}
*/
int main()
{
    //ejemploSumaComunSinLazyUpdate(); // Para que compile este, hay que comentar las lineas correspondientes en el codigo de SegmentTree
    ejemploSumaConLazyUpdate();
    return 0;
}
<|endoftext|>


<commit_before>#include "optionsdialog.h"
#include "optionsmodel.h"
#include "bitcoinamountfield.h"
#include "monitoreddatamapper.h"
#include "guiutil.h"
#include "bitcoinunits.h"
#include "qvaluecombobox.h"

#include <QHBoxLayout>
#include <QVBoxLayout>
#include <QPushButton>
#include <QListWidget>
#include <QStackedWidget>

#include <QCheckBox>
#include <QLabel>
#include <QLineEdit>
#include <QIntValidator>
#include <QDoubleValidator>
#include <QRegExpValidator>
#include <QDialogButtonBox>

/* First page of options */
class MainOptionsPage : public QWidget
{
    Q_OBJECT
public:
    explicit MainOptionsPage(QWidget *parent=0);

    void setMapper(MonitoredDataMapper *mapper);
private:
    QCheckBox *bitcoin_at_startup;
#ifndef Q_WS_MAC
    QCheckBox *minimize_to_tray;
#endif
    QCheckBox *map_port_upnp;
#ifndef Q_WS_MAC
    QCheckBox *minimize_on_close;
#endif
    QCheckBox *connect_socks4;
    QCheckBox *detach_database;
    QLineEdit *proxy_ip;
    QLineEdit *proxy_port;

signals:

public slots:

};

class DisplayOptionsPage : public QWidget
{
    Q_OBJECT
public:
    explicit DisplayOptionsPage(QWidget *parent=0);

    void setMapper(MonitoredDataMapper *mapper);
private:
    QValueComboBox *unit;
    QCheckBox *display_addresses;
signals:

public slots:

};

#include "optionsdialog.moc"

OptionsDialog::OptionsDialog(QWidget *parent):
    QDialog(parent), contents_widget(0), pages_widget(0),
    model(0), main_page(0), display_page(0)
{
    contents_widget = new QListWidget();
    contents_widget->setMaximumWidth(128);

    pages_widget = new QStackedWidget();
    pages_widget->setMinimumWidth(300);

    QListWidgetItem *item_main = new QListWidgetItem(tr("Main"));
    contents_widget->addItem(item_main);
    main_page = new MainOptionsPage(this);
    pages_widget->addWidget(main_page);

    QListWidgetItem *item_display = new QListWidgetItem(tr("Display"));
    contents_widget->addItem(item_display);
    display_page = new DisplayOptionsPage(this);
    pages_widget->addWidget(display_page);

    contents_widget->setCurrentRow(0);

    QHBoxLayout *main_layout = new QHBoxLayout();
    main_layout->addWidget(contents_widget);
    main_layout->addWidget(pages_widget, 1);

    QVBoxLayout *layout = new QVBoxLayout();
    layout->addLayout(main_layout);

    QDialogButtonBox *buttonbox = new QDialogButtonBox();
    buttonbox->setStandardButtons(QDialogButtonBox::Apply|QDialogButtonBox::Ok|QDialogButtonBox::Cancel);
    apply_button = buttonbox->button(QDialogButtonBox::Apply);
    layout->addWidget(buttonbox);

    setLayout(layout);
    setWindowTitle(tr("Options"));

    /* Widget-to-option mapper */
    mapper = new MonitoredDataMapper(this);
    mapper->setSubmitPolicy(QDataWidgetMapper::ManualSubmit);
    mapper->setOrientation(Qt::Vertical);
    /* enable apply button when data modified */
    connect(mapper, SIGNAL(viewModified()), this, SLOT(enableApply()));
    /* disable apply button when new data loaded */
    connect(mapper, SIGNAL(currentIndexChanged(int)), this, SLOT(disableApply()));

    /* Event bindings */
    connect(contents_widget, SIGNAL(currentRowChanged(int)), this, SLOT(changePage(int)));
    connect(buttonbox->button(QDialogButtonBox::Ok), SIGNAL(clicked()), this, SLOT(okClicked()));
    connect(buttonbox->button(QDialogButtonBox::Cancel), SIGNAL(clicked()), this, SLOT(cancelClicked()));
    connect(buttonbox->button(QDialogButtonBox::Apply), SIGNAL(clicked()), this, SLOT(applyClicked()));
}

void OptionsDialog::setModel(OptionsModel *model)
{
    this->model = model;

    mapper->setModel(model);
    main_page->setMapper(mapper);
    display_page->setMapper(mapper);

    mapper->toFirst();
}

void OptionsDialog::changePage(int index)
{
    pages_widget->setCurrentIndex(index);
}

void OptionsDialog::okClicked()
{
    mapper->submit();
    accept();
}

void OptionsDialog::cancelClicked()
{
    reject();
}

void OptionsDialog::applyClicked()
{
    mapper->submit();
    apply_button->setEnabled(false);
}

void OptionsDialog::enableApply()
{
    apply_button->setEnabled(true);
}

void OptionsDialog::disableApply()
{
    apply_button->setEnabled(false);
}

MainOptionsPage::MainOptionsPage(QWidget *parent):
        QWidget(parent)
{
    QVBoxLayout *layout = new QVBoxLayout();

    bitcoin_at_startup = new QCheckBox(tr("&Start Nu on window system startup"));
    bitcoin_at_startup->setToolTip(tr("Automatically start Nu after the computer is turned on"));
    layout->addWidget(bitcoin_at_startup);

#ifndef Q_WS_MAC
    minimize_to_tray = new QCheckBox(tr("&Minimize to the tray instead of the taskbar"));
    minimize_to_tray->setToolTip(tr("Show only a tray icon after minimizing the window"));
    layout->addWidget(minimize_to_tray);

    minimize_on_close = new QCheckBox(tr("M&inimize on close"));
    minimize_on_close->setToolTip(tr("Minimize instead of exit the application when the window is closed. When this option is enabled, the application will be closed only after selecting Quit in the menu."));
    layout->addWidget(minimize_on_close);
#endif

    map_port_upnp = new QCheckBox(tr("Map port using &UPnP"));
    map_port_upnp->setToolTip(tr("Automatically open the Nu client port on the router. This only works when your router supports UPnP and it is enabled."));
    layout->addWidget(map_port_upnp);

    connect_socks4 = new QCheckBox(tr("&Connect through SOCKS4 proxy:"));
    connect_socks4->setToolTip(tr("Connect to the Peershares network through a SOCKS4 proxy (e.g. when connecting through Tor)"));
    layout->addWidget(connect_socks4);

    QHBoxLayout *proxy_hbox = new QHBoxLayout();
    proxy_hbox->addSpacing(18);
    QLabel *proxy_ip_label = new QLabel(tr("Proxy &IP: "));
    proxy_hbox->addWidget(proxy_ip_label);
    proxy_ip = new QLineEdit();
    proxy_ip->setMaximumWidth(140);
    proxy_ip->setEnabled(false);
    proxy_ip->setValidator(new QRegExpValidator(QRegExp("[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}"), this));
    proxy_ip->setToolTip(tr("IP address of the proxy (e.g. 127.0.0.1)"));
    proxy_ip_label->setBuddy(proxy_ip);
    proxy_hbox->addWidget(proxy_ip);
    QLabel *proxy_port_label = new QLabel(tr("&Port: "));
    proxy_hbox->addWidget(proxy_port_label);
    proxy_port = new QLineEdit();
    proxy_port->setMaximumWidth(55);
    proxy_port->setValidator(new QIntValidator(0, 65535, this));
    proxy_port->setEnabled(false);
    proxy_port->setToolTip(tr("Port of the proxy (e.g. 1234)"));
    proxy_port_label->setBuddy(proxy_port);
    proxy_hbox->addWidget(proxy_port);
    proxy_hbox->addStretch(1);

    detach_database = new QCheckBox(tr("Detach databases at shutdown"));
    detach_database->setToolTip(tr("Detach block and address databases at shutdown. This means they can be moved to another data directory, but it slows down shutdown. The wallet is always detached."));
    layout->addWidget(detach_database);

    layout->addStretch(1); // Extra space at bottom

    setLayout(layout);

    connect(connect_socks4, SIGNAL(toggled(bool)), proxy_ip, SLOT(setEnabled(bool)));
    connect(connect_socks4, SIGNAL(toggled(bool)), proxy_port, SLOT(setEnabled(bool)));

#ifndef USE_UPNP
    map_port_upnp->setDisabled(true);
#endif
}

void MainOptionsPage::setMapper(MonitoredDataMapper *mapper)
{
    // Map model to widgets
    mapper->addMapping(bitcoin_at_startup, OptionsModel::StartAtStartup);
#ifndef Q_WS_MAC
    mapper->addMapping(minimize_to_tray, OptionsModel::MinimizeToTray);
#endif
    mapper->addMapping(map_port_upnp, OptionsModel::MapPortUPnP);
#ifndef Q_WS_MAC
    mapper->addMapping(minimize_on_close, OptionsModel::MinimizeOnClose);
#endif
    mapper->addMapping(connect_socks4, OptionsModel::ConnectSOCKS4);
    mapper->addMapping(proxy_ip, OptionsModel::ProxyIP);
    mapper->addMapping(proxy_port, OptionsModel::ProxyPort);
    mapper->addMapping(detach_database, OptionsModel::DetachDatabases);
}

DisplayOptionsPage::DisplayOptionsPage(QWidget *parent):
        QWidget(parent)
{
    QVBoxLayout *layout = new QVBoxLayout();

    QHBoxLayout *unit_hbox = new QHBoxLayout();
    unit_hbox->addSpacing(18);
    QLabel *unit_label = new QLabel(tr("&Unit to show amounts in: "));
    unit_hbox->addWidget(unit_label);
    unit = new QValueComboBox(this);
    unit->setModel(new BitcoinUnits(this));
    unit->setToolTip(tr("Choose the default subdivision unit to show in the interface, and when sending coins"));

    unit_label->setBuddy(unit);
    unit_hbox->addWidget(unit);

    layout->addLayout(unit_hbox);

    display_addresses = new QCheckBox(tr("&Display addresses in transaction list"), this);
    display_addresses->setToolTip(tr("Whether to show Nu addresses in the transaction list"));
    layout->addWidget(display_addresses);

    layout->addStretch();

    setLayout(layout);
}

void DisplayOptionsPage::setMapper(MonitoredDataMapper *mapper)
{
    mapper->addMapping(unit, OptionsModel::DisplayUnit);
    mapper->addMapping(display_addresses, OptionsModel::DisplayAddresses);
}
<commit_msg>Added proxy hbox that was incorrectly removed in 8417837a0<commit_after>#include "optionsdialog.h"
#include "optionsmodel.h"
#include "bitcoinamountfield.h"
#include "monitoreddatamapper.h"
#include "guiutil.h"
#include "bitcoinunits.h"
#include "qvaluecombobox.h"

#include <QHBoxLayout>
#include <QVBoxLayout>
#include <QPushButton>
#include <QListWidget>
#include <QStackedWidget>

#include <QCheckBox>
#include <QLabel>
#include <QLineEdit>
#include <QIntValidator>
#include <QDoubleValidator>
#include <QRegExpValidator>
#include <QDialogButtonBox>

/* First page of options */
class MainOptionsPage : public QWidget
{
    Q_OBJECT
public:
    explicit MainOptionsPage(QWidget *parent=0);

    void setMapper(MonitoredDataMapper *mapper);
private:
    QCheckBox *bitcoin_at_startup;
#ifndef Q_WS_MAC
    QCheckBox *minimize_to_tray;
#endif
    QCheckBox *map_port_upnp;
#ifndef Q_WS_MAC
    QCheckBox *minimize_on_close;
#endif
    QCheckBox *connect_socks4;
    QCheckBox *detach_database;
    QLineEdit *proxy_ip;
    QLineEdit *proxy_port;

signals:

public slots:

};

class DisplayOptionsPage : public QWidget
{
    Q_OBJECT
public:
    explicit DisplayOptionsPage(QWidget *parent=0);

    void setMapper(MonitoredDataMapper *mapper);
private:
    QValueComboBox *unit;
    QCheckBox *display_addresses;
signals:

public slots:

};

#include "optionsdialog.moc"

OptionsDialog::OptionsDialog(QWidget *parent):
    QDialog(parent), contents_widget(0), pages_widget(0),
    model(0), main_page(0), display_page(0)
{
    contents_widget = new QListWidget();
    contents_widget->setMaximumWidth(128);

    pages_widget = new QStackedWidget();
    pages_widget->setMinimumWidth(300);

    QListWidgetItem *item_main = new QListWidgetItem(tr("Main"));
    contents_widget->addItem(item_main);
    main_page = new MainOptionsPage(this);
    pages_widget->addWidget(main_page);

    QListWidgetItem *item_display = new QListWidgetItem(tr("Display"));
    contents_widget->addItem(item_display);
    display_page = new DisplayOptionsPage(this);
    pages_widget->addWidget(display_page);

    contents_widget->setCurrentRow(0);

    QHBoxLayout *main_layout = new QHBoxLayout();
    main_layout->addWidget(contents_widget);
    main_layout->addWidget(pages_widget, 1);

    QVBoxLayout *layout = new QVBoxLayout();
    layout->addLayout(main_layout);

    QDialogButtonBox *buttonbox = new QDialogButtonBox();
    buttonbox->setStandardButtons(QDialogButtonBox::Apply|QDialogButtonBox::Ok|QDialogButtonBox::Cancel);
    apply_button = buttonbox->button(QDialogButtonBox::Apply);
    layout->addWidget(buttonbox);

    setLayout(layout);
    setWindowTitle(tr("Options"));

    /* Widget-to-option mapper */
    mapper = new MonitoredDataMapper(this);
    mapper->setSubmitPolicy(QDataWidgetMapper::ManualSubmit);
    mapper->setOrientation(Qt::Vertical);
    /* enable apply button when data modified */
    connect(mapper, SIGNAL(viewModified()), this, SLOT(enableApply()));
    /* disable apply button when new data loaded */
    connect(mapper, SIGNAL(currentIndexChanged(int)), this, SLOT(disableApply()));

    /* Event bindings */
    connect(contents_widget, SIGNAL(currentRowChanged(int)), this, SLOT(changePage(int)));
    connect(buttonbox->button(QDialogButtonBox::Ok), SIGNAL(clicked()), this, SLOT(okClicked()));
    connect(buttonbox->button(QDialogButtonBox::Cancel), SIGNAL(clicked()), this, SLOT(cancelClicked()));
    connect(buttonbox->button(QDialogButtonBox::Apply), SIGNAL(clicked()), this, SLOT(applyClicked()));
}

void OptionsDialog::setModel(OptionsModel *model)
{
    this->model = model;

    mapper->setModel(model);
    main_page->setMapper(mapper);
    display_page->setMapper(mapper);

    mapper->toFirst();
}

void OptionsDialog::changePage(int index)
{
    pages_widget->setCurrentIndex(index);
}

void OptionsDialog::okClicked()
{
    mapper->submit();
    accept();
}

void OptionsDialog::cancelClicked()
{
    reject();
}

void OptionsDialog::applyClicked()
{
    mapper->submit();
    apply_button->setEnabled(false);
}

void OptionsDialog::enableApply()
{
    apply_button->setEnabled(true);
}

void OptionsDialog::disableApply()
{
    apply_button->setEnabled(false);
}

MainOptionsPage::MainOptionsPage(QWidget *parent):
        QWidget(parent)
{
    QVBoxLayout *layout = new QVBoxLayout();

    bitcoin_at_startup = new QCheckBox(tr("&Start Nu on window system startup"));
    bitcoin_at_startup->setToolTip(tr("Automatically start Nu after the computer is turned on"));
    layout->addWidget(bitcoin_at_startup);

#ifndef Q_WS_MAC
    minimize_to_tray = new QCheckBox(tr("&Minimize to the tray instead of the taskbar"));
    minimize_to_tray->setToolTip(tr("Show only a tray icon after minimizing the window"));
    layout->addWidget(minimize_to_tray);

    minimize_on_close = new QCheckBox(tr("M&inimize on close"));
    minimize_on_close->setToolTip(tr("Minimize instead of exit the application when the window is closed. When this option is enabled, the application will be closed only after selecting Quit in the menu."));
    layout->addWidget(minimize_on_close);
#endif

    map_port_upnp = new QCheckBox(tr("Map port using &UPnP"));
    map_port_upnp->setToolTip(tr("Automatically open the Nu client port on the router. This only works when your router supports UPnP and it is enabled."));
    layout->addWidget(map_port_upnp);

    connect_socks4 = new QCheckBox(tr("&Connect through SOCKS4 proxy:"));
    connect_socks4->setToolTip(tr("Connect to the Peershares network through a SOCKS4 proxy (e.g. when connecting through Tor)"));
    layout->addWidget(connect_socks4);

    QHBoxLayout *proxy_hbox = new QHBoxLayout();
    proxy_hbox->addSpacing(18);
    QLabel *proxy_ip_label = new QLabel(tr("Proxy &IP: "));
    proxy_hbox->addWidget(proxy_ip_label);
    proxy_ip = new QLineEdit();
    proxy_ip->setMaximumWidth(140);
    proxy_ip->setEnabled(false);
    proxy_ip->setValidator(new QRegExpValidator(QRegExp("[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}"), this));
    proxy_ip->setToolTip(tr("IP address of the proxy (e.g. 127.0.0.1)"));
    proxy_ip_label->setBuddy(proxy_ip);
    proxy_hbox->addWidget(proxy_ip);
    QLabel *proxy_port_label = new QLabel(tr("&Port: "));
    proxy_hbox->addWidget(proxy_port_label);
    proxy_port = new QLineEdit();
    proxy_port->setMaximumWidth(55);
    proxy_port->setValidator(new QIntValidator(0, 65535, this));
    proxy_port->setEnabled(false);
    proxy_port->setToolTip(tr("Port of the proxy (e.g. 1234)"));
    proxy_port_label->setBuddy(proxy_port);
    proxy_hbox->addWidget(proxy_port);
    proxy_hbox->addStretch(1);
    layout->addLayout(proxy_hbox);

    detach_database = new QCheckBox(tr("Detach databases at shutdown"));
    detach_database->setToolTip(tr("Detach block and address databases at shutdown. This means they can be moved to another data directory, but it slows down shutdown. The wallet is always detached."));
    layout->addWidget(detach_database);

    layout->addStretch(1); // Extra space at bottom

    setLayout(layout);

    connect(connect_socks4, SIGNAL(toggled(bool)), proxy_ip, SLOT(setEnabled(bool)));
    connect(connect_socks4, SIGNAL(toggled(bool)), proxy_port, SLOT(setEnabled(bool)));

#ifndef USE_UPNP
    map_port_upnp->setDisabled(true);
#endif
}

void MainOptionsPage::setMapper(MonitoredDataMapper *mapper)
{
    // Map model to widgets
    mapper->addMapping(bitcoin_at_startup, OptionsModel::StartAtStartup);
#ifndef Q_WS_MAC
    mapper->addMapping(minimize_to_tray, OptionsModel::MinimizeToTray);
#endif
    mapper->addMapping(map_port_upnp, OptionsModel::MapPortUPnP);
#ifndef Q_WS_MAC
    mapper->addMapping(minimize_on_close, OptionsModel::MinimizeOnClose);
#endif
    mapper->addMapping(connect_socks4, OptionsModel::ConnectSOCKS4);
    mapper->addMapping(proxy_ip, OptionsModel::ProxyIP);
    mapper->addMapping(proxy_port, OptionsModel::ProxyPort);
    mapper->addMapping(detach_database, OptionsModel::DetachDatabases);
}

DisplayOptionsPage::DisplayOptionsPage(QWidget *parent):
        QWidget(parent)
{
    QVBoxLayout *layout = new QVBoxLayout();

    QHBoxLayout *unit_hbox = new QHBoxLayout();
    unit_hbox->addSpacing(18);
    QLabel *unit_label = new QLabel(tr("&Unit to show amounts in: "));
    unit_hbox->addWidget(unit_label);
    unit = new QValueComboBox(this);
    unit->setModel(new BitcoinUnits(this));
    unit->setToolTip(tr("Choose the default subdivision unit to show in the interface, and when sending coins"));

    unit_label->setBuddy(unit);
    unit_hbox->addWidget(unit);

    layout->addLayout(unit_hbox);

    display_addresses = new QCheckBox(tr("&Display addresses in transaction list"), this);
    display_addresses->setToolTip(tr("Whether to show Nu addresses in the transaction list"));
    layout->addWidget(display_addresses);

    layout->addStretch();

    setLayout(layout);
}

void DisplayOptionsPage::setMapper(MonitoredDataMapper *mapper)
{
    mapper->addMapping(unit, OptionsModel::DisplayUnit);
    mapper->addMapping(display_addresses, OptionsModel::DisplayAddresses);
}
<|endoftext|>