<commit_before>/**
 * @file
 *
 * Standard headers that should be included for all C++ files generated by
 * the compiler.
 */
#pragma once

#include "bi/lib/Span.hpp"
#include "bi/lib/Index.hpp"
#include "bi/lib/Range.hpp"
#include "bi/lib/Frame.hpp"
#include "bi/lib/View.hpp"
#include "bi/lib/Array.hpp"
#include "bi/lib/Markable.hpp"
#include "bi/lib/Object.hpp"
#include "bi/lib/Pointer.hpp"
#include "bi/lib/FiberState.hpp"
#include "bi/lib/Fiber.hpp"

#include "boost/optional.hpp"

#include <getopt.h>
#include <gc.h>

#include <utility>
#include <functional>
#include <string>
#include <cstdlib>
#include <cassert>

namespace bi {
/**
 * Left tilde (`<~`) operator
 */
template<class Left, class Right>
void left_tilde_(Left& left, const Right& right) {
  left = right->simulate_();
}

/**
 * Right tilde (`~>`) operator
 */
template<class Left, class Right>
auto right_tilde_(const Left& left, const Right& right) {
  return right->observe_(left);
}

/**
 * Tilde (`~`) operator
 */
template<class Left, class Right>
void tilde_(Left& left, const Right& right) {
  assert(left->isUninitialized_());
  if (!left->isMissing_()) {
    right_tilde_(left->value_(), right);
  }
  left = right;
}

/**
 * Make a span.
 *
 * @ingroup library
 *
 * @param length Length.
 */
inline auto make_span(const size_t length) {
  return Span<mutable_value,1,mutable_value>(length);
}

/**
 * Make an index.
 *
 * @ingroup library
 *
 * @param index Index.
 */
inline auto make_index(const ptrdiff_t i) {
  return Index<mutable_value>(i);
}

/**
 * Make a range.
 *
 * @ingroup library
 *
 * @param start First index.
 * @param end Last index.
 */
inline auto make_range(const ptrdiff_t start, const ptrdiff_t end) {
  return Range<mutable_value,mutable_value,1>(start, end - start + 1);
}

/**
 * Make a frame, no arguments.
 *
 * @ingroup library
 */
inline auto make_frame() {
  return EmptyFrame();
}

/**
 * Make a frame, single argument.
 *
 * @ingroup library
 */
template<size_t length_value, ptrdiff_t stride_value, size_t lead_value>
auto make_frame(const Span<length_value,stride_value,lead_value>& arg) {
  auto tail = make_frame();
  auto head = arg;
  return NonemptyFrame<decltype(tail),decltype(head)>(tail, head);
}

/**
 * Make a frame, single argument.
 *
 * @ingroup library
 */
inline auto make_frame(const size_t arg) {
  return make_frame(make_span(arg));
}

/**
 * Make a frame, multiple arguments.
 *
 * @ingroup library
 */
template<size_t length_value, ptrdiff_t stride_value, size_t lead_value,
    class ... Args>
auto make_frame(const Span<length_value,stride_value,lead_value>& arg,
    Args ... args) {
  return make_frame(make_frame(arg), args...);
}

/**
 * Make a frame, multiple arguments.
 *
 * @ingroup library
 */
template<class ... Args>
auto make_frame(const size_t arg, Args ... args) {
  return make_frame(make_frame(arg), args...);
}

/**
 * Make a frame, tail and single argument.
 *
 * @ingroup library
 */
template<class Tail, class Head, size_t length_value, ptrdiff_t stride_value,
    size_t lead_value>
auto make_frame(const NonemptyFrame<Tail,Head>& frame,
    const Span<length_value,stride_value,lead_value>& arg) {
  auto tail = frame;
  auto head = arg;
  return NonemptyFrame<decltype(tail),decltype(head)>(tail, head);
}

/**
 * Make a frame, tail and single argument.
 *
 * @ingroup library
 */
template<class Tail, class Head>
auto make_frame(const NonemptyFrame<Tail,Head>& frame, const size_t arg) {
  return make_frame(frame, make_span(arg));
}

/**
 * Make a frame, tail and multiple arguments.
 *
 * @ingroup library
 */
template<class Tail, class Head, class Arg, class ... Args>
auto make_frame(const NonemptyFrame<Tail,Head>& tail, const Arg& arg,
    Args ... args) {
  return make_frame(make_frame(tail, arg), args...);
}

/**
 * Make a frame, tail and multiple arguments.
 *
 * @ingroup library
 */
template<class Tail, class Head, class ... Args>
auto make_frame(const NonemptyFrame<Tail,Head>& tail, const size_t arg,
    Args ... args) {
  return make_frame(make_frame(tail, make_span(arg)), args...);
}

/**
 * Make a view, no arguments.
 *
 * @ingroup library
 */
inline auto make_view() {
  return EmptyView();
}

/**
 * Make a view, single argument.
 *
 * @ingroup library
 */
template<ptrdiff_t offset_value, size_t length_value, ptrdiff_t stride_value>
auto make_view(const Range<offset_value,length_value,stride_value>& arg) {
  auto tail = make_view();
  auto head = arg;
  return NonemptyView<decltype(tail),decltype(head)>(tail, head);
}

/**
 * Make a view, single argument.
 *
 * @ingroup library
 */
template<ptrdiff_t offset_value>
auto make_view(const Index<offset_value>& arg) {
  auto tail = make_view();
  auto head = arg;
  return NonemptyView<decltype(tail),decltype(head)>(tail, head);
}

/**
 * Make a view, single argument.
 *
 * @ingroup library
 */
inline auto make_view(const ptrdiff_t arg) {
  return make_view(make_index(arg));
}

/**
 * Make a view, multiple arguments.
 *
 * @ingroup library
 */
template<ptrdiff_t offset_value, size_t length_value, ptrdiff_t stride_value,
    class ... Args>
auto make_view(const Range<offset_value,length_value,stride_value>& arg,
    Args ... args) {
  return make_view(make_view(arg), args...);
}

/**
 * Make a view, multiple arguments.
 *
 * @ingroup library
 */
template<ptrdiff_t offset_value, class ... Args>
auto make_view(const Index<offset_value>& arg, Args ... args) {
  return make_view(make_view(arg), args...);
}

/**
 * Make a view, multiple arguments.
 *
 * @ingroup library
 */
template<class ... Args>
auto make_view(const ptrdiff_t arg, Args ... args) {
  return make_view(make_index(arg), args...);
}

/**
 * Make a view, tail plus single argument.
 *
 * @ingroup library
 */
template<class Tail, class Head, ptrdiff_t offset_value, size_t length_value,
    ptrdiff_t stride_value>
auto make_view(const NonemptyView<Tail,Head>& view,
    const Range<offset_value,length_value,stride_value>& arg) {
  auto tail = view;
  auto head = arg;
  return NonemptyView<decltype(tail),decltype(head)>(tail, head);
}

/**
 * Make a view, tail plus single argument.
 *
 * @ingroup library
 */
template<class Tail, class Head, ptrdiff_t offset_value>
auto make_view(const NonemptyView<Tail,Head>& view,
    const Index<offset_value>& arg) {
  auto tail = view;
  auto head = arg;
  return NonemptyView<decltype(tail),decltype(head)>(tail, head);
}

/**
 * Make a view, tail plus single argument.
 *
 * @ingroup library
 */
template<class Tail, class Head>
auto make_view(const NonemptyView<Tail,Head>& view, const ptrdiff_t arg) {
  return make_view(view, make_index(arg));
}

/**
 * Make a view, tail plus multiple arguments.
 *
 * @ingroup library
 */
template<class Tail, class Head, class Arg, class ... Args>
auto make_view(const NonemptyView<Tail,Head>& tail, Arg arg, Args ... args) {
  return make_view(make_view(tail, arg), args...);
}

/**
 * Make an array.
 *
 * @ingroup library
 *
 * @tparam Type Value type.
 * @tparam Frame Frame type.
 *
 * @param frame Frame.
 *
 * @return The array.
 */
template<class Type, class Frame = EmptyFrame>
auto make_array(const Frame& frame = EmptyFrame()) {
  return Array<Type,Frame>(frame);
}

/**
 * Make an object.
 *
 * @ingroup library
 *
 * @tparam Type Value type.
 * @tparam Args Constructor parameter types.
 *
 * @param args Constructor arguments.
 *
 * @return Pointer to the object.
 */
template<class Type, class ... Args>
Pointer<Type> make_object(Args ... args) {
  auto raw = new (GC_MALLOC(sizeof(Type))) Type(args...);
  return Pointer<Type>(raw);
}

/**
 * Shallow-copy an object.
 *
 * @ingroup library
 *
 * @tparam Type Value type.
 *
 * @param o The object to copy.
 *
 * @return Pointer to the new object.
 */
template<class Type>
Type* copy_object(Type* o) {
  return new (GC_MALLOC(sizeof(Type))) Type(*o);
}

/**
 * Make a fiber.
 *
 * @tparam YieldType The yield type of the fiber.
 * @tparam StateType The state type of the fiber.
 * @tparam Args Fiber state constructor parameter types.
 *
 * @param args Fiber state constructor arguments.
 *
 * For a member fiber, the first argument should be a raw pointer to the
 * containing object.
 */
template<class YieldType, class StateType, class... Args>
static Fiber<YieldType> make_fiber(Args... args) {
  /* the key here is to ensure that both the internal fiber state, and the
   * pointer to the containing object (for a member fiber), are relative to
   * the new fiber's heap, and not that of the calling fiber, or the
   * process */
  Fiber<YieldType> fiber;
  Heap* yieldTo = fiberHeap;
  fiberHeap = &fiber.heap;  // ensures on the new fiber's heap
  fiber.state = make_object<StateType>(args...);
  fiberHeap = yieldTo;
  return fiber;
}
}
<commit_msg>Removed assertion check from libbirch tilde_ function.<commit_after>/**
 * @file
 *
 * Standard headers that should be included for all C++ files generated by
 * the compiler.
 */
#pragma once

#include "bi/lib/Span.hpp"
#include "bi/lib/Index.hpp"
#include "bi/lib/Range.hpp"
#include "bi/lib/Frame.hpp"
#include "bi/lib/View.hpp"
#include "bi/lib/Array.hpp"
#include "bi/lib/Markable.hpp"
#include "bi/lib/Object.hpp"
#include "bi/lib/Pointer.hpp"
#include "bi/lib/FiberState.hpp"
#include "bi/lib/Fiber.hpp"

#include "boost/optional.hpp"

#include <getopt.h>
#include <gc.h>

#include <utility>
#include <functional>
#include <string>
#include <cstdlib>
#include <cassert>

namespace bi {
/**
 * Left tilde (`<~`) operator
 */
template<class Left, class Right>
void left_tilde_(Left& left, const Right& right) {
  left = right->simulate_();
}

/**
 * Right tilde (`~>`) operator
 */
template<class Left, class Right>
auto right_tilde_(const Left& left, const Right& right) {
  return right->observe_(left);
}

/**
 * Tilde (`~`) operator
 */
template<class Left, class Right>
void tilde_(Left& left, const Right& right) {
  if (!left->isMissing_()) {
    right_tilde_(left->value_(), right);
  }
  left = right;
}

/**
 * Make a span.
 *
 * @ingroup library
 *
 * @param length Length.
 */
inline auto make_span(const size_t length) {
  return Span<mutable_value,1,mutable_value>(length);
}

/**
 * Make an index.
 *
 * @ingroup library
 *
 * @param index Index.
 */
inline auto make_index(const ptrdiff_t i) {
  return Index<mutable_value>(i);
}

/**
 * Make a range.
 *
 * @ingroup library
 *
 * @param start First index.
 * @param end Last index.
 */
inline auto make_range(const ptrdiff_t start, const ptrdiff_t end) {
  return Range<mutable_value,mutable_value,1>(start, end - start + 1);
}

/**
 * Make a frame, no arguments.
 *
 * @ingroup library
 */
inline auto make_frame() {
  return EmptyFrame();
}

/**
 * Make a frame, single argument.
 *
 * @ingroup library
 */
template<size_t length_value, ptrdiff_t stride_value, size_t lead_value>
auto make_frame(const Span<length_value,stride_value,lead_value>& arg) {
  auto tail = make_frame();
  auto head = arg;
  return NonemptyFrame<decltype(tail),decltype(head)>(tail, head);
}

/**
 * Make a frame, single argument.
 *
 * @ingroup library
 */
inline auto make_frame(const size_t arg) {
  return make_frame(make_span(arg));
}

/**
 * Make a frame, multiple arguments.
 *
 * @ingroup library
 */
template<size_t length_value, ptrdiff_t stride_value, size_t lead_value,
    class ... Args>
auto make_frame(const Span<length_value,stride_value,lead_value>& arg,
    Args ... args) {
  return make_frame(make_frame(arg), args...);
}

/**
 * Make a frame, multiple arguments.
 *
 * @ingroup library
 */
template<class ... Args>
auto make_frame(const size_t arg, Args ... args) {
  return make_frame(make_frame(arg), args...);
}

/**
 * Make a frame, tail and single argument.
 *
 * @ingroup library
 */
template<class Tail, class Head, size_t length_value, ptrdiff_t stride_value,
    size_t lead_value>
auto make_frame(const NonemptyFrame<Tail,Head>& frame,
    const Span<length_value,stride_value,lead_value>& arg) {
  auto tail = frame;
  auto head = arg;
  return NonemptyFrame<decltype(tail),decltype(head)>(tail, head);
}

/**
 * Make a frame, tail and single argument.
 *
 * @ingroup library
 */
template<class Tail, class Head>
auto make_frame(const NonemptyFrame<Tail,Head>& frame, const size_t arg) {
  return make_frame(frame, make_span(arg));
}

/**
 * Make a frame, tail and multiple arguments.
 *
 * @ingroup library
 */
template<class Tail, class Head, class Arg, class ... Args>
auto make_frame(const NonemptyFrame<Tail,Head>& tail, const Arg& arg,
    Args ... args) {
  return make_frame(make_frame(tail, arg), args...);
}

/**
 * Make a frame, tail and multiple arguments.
 *
 * @ingroup library
 */
template<class Tail, class Head, class ... Args>
auto make_frame(const NonemptyFrame<Tail,Head>& tail, const size_t arg,
    Args ... args) {
  return make_frame(make_frame(tail, make_span(arg)), args...);
}

/**
 * Make a view, no arguments.
 *
 * @ingroup library
 */
inline auto make_view() {
  return EmptyView();
}

/**
 * Make a view, single argument.
 *
 * @ingroup library
 */
template<ptrdiff_t offset_value, size_t length_value, ptrdiff_t stride_value>
auto make_view(const Range<offset_value,length_value,stride_value>& arg) {
  auto tail = make_view();
  auto head = arg;
  return NonemptyView<decltype(tail),decltype(head)>(tail, head);
}

/**
 * Make a view, single argument.
 *
 * @ingroup library
 */
template<ptrdiff_t offset_value>
auto make_view(const Index<offset_value>& arg) {
  auto tail = make_view();
  auto head = arg;
  return NonemptyView<decltype(tail),decltype(head)>(tail, head);
}

/**
 * Make a view, single argument.
 *
 * @ingroup library
 */
inline auto make_view(const ptrdiff_t arg) {
  return make_view(make_index(arg));
}

/**
 * Make a view, multiple arguments.
 *
 * @ingroup library
 */
template<ptrdiff_t offset_value, size_t length_value, ptrdiff_t stride_value,
    class ... Args>
auto make_view(const Range<offset_value,length_value,stride_value>& arg,
    Args ... args) {
  return make_view(make_view(arg), args...);
}

/**
 * Make a view, multiple arguments.
 *
 * @ingroup library
 */
template<ptrdiff_t offset_value, class ... Args>
auto make_view(const Index<offset_value>& arg, Args ... args) {
  return make_view(make_view(arg), args...);
}

/**
 * Make a view, multiple arguments.
 *
 * @ingroup library
 */
template<class ... Args>
auto make_view(const ptrdiff_t arg, Args ... args) {
  return make_view(make_index(arg), args...);
}

/**
 * Make a view, tail plus single argument.
 *
 * @ingroup library
 */
template<class Tail, class Head, ptrdiff_t offset_value, size_t length_value,
    ptrdiff_t stride_value>
auto make_view(const NonemptyView<Tail,Head>& view,
    const Range<offset_value,length_value,stride_value>& arg) {
  auto tail = view;
  auto head = arg;
  return NonemptyView<decltype(tail),decltype(head)>(tail, head);
}

/**
 * Make a view, tail plus single argument.
 *
 * @ingroup library
 */
template<class Tail, class Head, ptrdiff_t offset_value>
auto make_view(const NonemptyView<Tail,Head>& view,
    const Index<offset_value>& arg) {
  auto tail = view;
  auto head = arg;
  return NonemptyView<decltype(tail),decltype(head)>(tail, head);
}

/**
 * Make a view, tail plus single argument.
 *
 * @ingroup library
 */
template<class Tail, class Head>
auto make_view(const NonemptyView<Tail,Head>& view, const ptrdiff_t arg) {
  return make_view(view, make_index(arg));
}

/**
 * Make a view, tail plus multiple arguments.
 *
 * @ingroup library
 */
template<class Tail, class Head, class Arg, class ... Args>
auto make_view(const NonemptyView<Tail,Head>& tail, Arg arg, Args ... args) {
  return make_view(make_view(tail, arg), args...);
}

/**
 * Make an array.
 *
 * @ingroup library
 *
 * @tparam Type Value type.
 * @tparam Frame Frame type.
 *
 * @param frame Frame.
 *
 * @return The array.
 */
template<class Type, class Frame = EmptyFrame>
auto make_array(const Frame& frame = EmptyFrame()) {
  return Array<Type,Frame>(frame);
}

/**
 * Make an object.
 *
 * @ingroup library
 *
 * @tparam Type Value type.
 * @tparam Args Constructor parameter types.
 *
 * @param args Constructor arguments.
 *
 * @return Pointer to the object.
 */
template<class Type, class ... Args>
Pointer<Type> make_object(Args ... args) {
  auto raw = new (GC_MALLOC(sizeof(Type))) Type(args...);
  return Pointer<Type>(raw);
}

/**
 * Shallow-copy an object.
 *
 * @ingroup library
 *
 * @tparam Type Value type.
 *
 * @param o The object to copy.
 *
 * @return Pointer to the new object.
 */
template<class Type>
Type* copy_object(Type* o) {
  return new (GC_MALLOC(sizeof(Type))) Type(*o);
}

/**
 * Make a fiber.
 *
 * @tparam YieldType The yield type of the fiber.
 * @tparam StateType The state type of the fiber.
 * @tparam Args Fiber state constructor parameter types.
 *
 * @param args Fiber state constructor arguments.
 *
 * For a member fiber, the first argument should be a raw pointer to the
 * containing object.
 */
template<class YieldType, class StateType, class... Args>
static Fiber<YieldType> make_fiber(Args... args) {
  /* the key here is to ensure that both the internal fiber state, and the
   * pointer to the containing object (for a member fiber), are relative to
   * the new fiber's heap, and not that of the calling fiber, or the
   * process */
  Fiber<YieldType> fiber;
  Heap* yieldTo = fiberHeap;
  fiberHeap = &fiber.heap;  // ensures on the new fiber's heap
  fiber.state = make_object<StateType>(args...);
  fiberHeap = yieldTo;
  return fiber;
}
}
<|endoftext|>


<commit_before>/******************************************************************************
 *                    _   _____   __________                                  *
 *                   | | / / _ | / __/_  __/     Visibility                   *
 *                   | |/ / __ |_\ \  / /          Across                     *
 *                   |___/_/ |_/___/ /_/       Space and Time                 *
 *                                                                            *
 * This file is part of VAST. It is subject to the license terms in the       *
 * LICENSE file found in the top-level directory of this distribution and at  *
 * http://vast.io/license. No part of VAST, including this file, may be       *
 * copied, modified, propagated, or distributed except according to the terms *
 * contained in the LICENSE file.                                             *
 ******************************************************************************/

#pragma once

#include <string>
#include <type_traits>
#include <utility>

#include <caf/config_value.hpp>
#include <caf/io/middleman.hpp>

#include "vast/command.hpp"
#include "vast/concept/parseable/vast/endpoint.hpp"
#include "vast/defaults.hpp"
#include "vast/detail/make_io_stream.hpp"
#include "vast/endpoint.hpp"
#include "vast/error.hpp"
#include "vast/format/reader.hpp"
#include "vast/logger.hpp"
#include "vast/system/datagram_source.hpp"
#include "vast/system/source.hpp"
#include "vast/system/source_command.hpp"
#include "vast/table_slice_builder.hpp"
#include "vast/table_slice_builder_factory.hpp"

namespace vast::system {

/// Default implementation for import sub-commands. Compatible with Bro and MRT
/// formats.
/// @relates application
template <class Reader, class Defaults>
caf::message reader_command(const command& cmd, caf::actor_system& sys,
                            caf::settings& options,
                            command::argument_iterator first,
                            command::argument_iterator last) {
  VAST_TRACE(VAST_ARG(options), VAST_ARG("args", first, last));
  std::string category = Defaults::category;
  auto uri = caf::get_if<std::string>(&options, category + ".listen");
  auto file = caf::get_if<std::string>(&options, category + ".read");
  auto max_events = caf::get_if<size_t>(&options, category + ".max-events");
  if (uri && file)
    return caf::make_message(make_error(ec::invalid_configuration,
                                        "only one source possible (-r or -l)"));
  if (!uri && !file) {
    using inputs = vast::format::reader::inputs;
    if constexpr (Reader::defaults::input == inputs::inet)
      uri = std::string{Reader::defaults::uri};
    else
      file = std::string{Reader::defaults::path};
  }
  auto slice_type = defaults::import::table_slice_type(sys, options);
  auto factory = vast::factory<vast::table_slice_builder>::get(slice_type);
  if (factory == nullptr)
    return caf::make_message(
      make_error(vast::ec::unspecified, "unknown table_slice_builder factory"));
  auto slice_size = get_or(options, "system.table-slice-size",
                           defaults::system::table_slice_size);
  if (uri) {
    endpoint ep;
    if (!vast::parsers::endpoint(*uri, ep))
      return caf::make_message(
        make_error(vast::ec::parse_error, "unable to parse endpoint", *uri));
    if (ep.port.type() == port::unknown) {
      using inputs = vast::format::reader::inputs;
      if constexpr (Reader::defaults::input == inputs::inet) {
        endpoint default_ep;
        vast::parsers::endpoint(Reader::defaults::uri, default_ep);
        ep.port = port{ep.port.number(), default_ep.port.type()};
      } else {
        // Fall back to tcp if we don't know anything else.
        ep.port = port{ep.port.number(), port::tcp};
      }
    }
    Reader reader{slice_type};
    auto run = [&](auto&& source) {
      auto& mm = sys.middleman();
      auto src = mm.spawn_broker(std::forward<decltype(source)>(source),
                                 ep.port.number(), std::move(reader), factory,
                                 slice_size, max_events);
      return source_command(cmd, sys, std::move(src), options, first, last);
    };
    switch (ep.port.type()) {
      default:
        return caf::make_message(
          make_error(vast::ec::unimplemented,
                     "port type not supported:", ep.port.type()));
      case port::udp:
        return run(datagram_source<Reader>);
    }
  } else {
    auto uds = get_or(options, category + ".uds", false);
    auto in = detail::make_input_stream(*file, uds);
    if (!in)
      return caf::make_message(std::move(in.error()));
    Reader reader{slice_type, std::move(*in)};
    auto src = sys.spawn(source<Reader>, std::move(reader), factory, slice_size,
                         max_events);
    return source_command(cmd, sys, std::move(src), options, first, last);
  }
}

} // namespace vast::system
<commit_msg>Fix max-events for import subcommands<commit_after>/******************************************************************************
 *                    _   _____   __________                                  *
 *                   | | / / _ | / __/_  __/     Visibility                   *
 *                   | |/ / __ |_\ \  / /          Across                     *
 *                   |___/_/ |_/___/ /_/       Space and Time                 *
 *                                                                            *
 * This file is part of VAST. It is subject to the license terms in the       *
 * LICENSE file found in the top-level directory of this distribution and at  *
 * http://vast.io/license. No part of VAST, including this file, may be       *
 * copied, modified, propagated, or distributed except according to the terms *
 * contained in the LICENSE file.                                             *
 ******************************************************************************/

#pragma once

#include <string>
#include <type_traits>
#include <utility>

#include <caf/config_value.hpp>
#include <caf/io/middleman.hpp>

#include "vast/command.hpp"
#include "vast/concept/parseable/vast/endpoint.hpp"
#include "vast/defaults.hpp"
#include "vast/detail/make_io_stream.hpp"
#include "vast/endpoint.hpp"
#include "vast/error.hpp"
#include "vast/format/reader.hpp"
#include "vast/logger.hpp"
#include "vast/system/datagram_source.hpp"
#include "vast/system/source.hpp"
#include "vast/system/source_command.hpp"
#include "vast/table_slice_builder.hpp"
#include "vast/table_slice_builder_factory.hpp"

namespace vast::system {

/// Default implementation for import sub-commands. Compatible with Bro and MRT
/// formats.
/// @relates application
template <class Reader, class Defaults>
caf::message reader_command(const command& cmd, caf::actor_system& sys,
                            caf::settings& options,
                            command::argument_iterator first,
                            command::argument_iterator last) {
  VAST_TRACE(VAST_ARG(options), VAST_ARG("args", first, last));
  std::string category = Defaults::category;
  auto uri = caf::get_if<std::string>(&options, category + ".listen");
  auto file = caf::get_if<std::string>(&options, category + ".read");
  auto max_events = caf::get_if<size_t>(&options, "import.max-events");
  if (uri && file)
    return caf::make_message(make_error(ec::invalid_configuration,
                                        "only one source possible (-r or -l)"));
  if (!uri && !file) {
    using inputs = vast::format::reader::inputs;
    if constexpr (Reader::defaults::input == inputs::inet)
      uri = std::string{Reader::defaults::uri};
    else
      file = std::string{Reader::defaults::path};
  }
  auto slice_type = defaults::import::table_slice_type(sys, options);
  auto factory = vast::factory<vast::table_slice_builder>::get(slice_type);
  if (factory == nullptr)
    return caf::make_message(
      make_error(vast::ec::unspecified, "unknown table_slice_builder factory"));
  auto slice_size = get_or(options, "system.table-slice-size",
                           defaults::system::table_slice_size);
  if (uri) {
    endpoint ep;
    if (!vast::parsers::endpoint(*uri, ep))
      return caf::make_message(
        make_error(vast::ec::parse_error, "unable to parse endpoint", *uri));
    if (ep.port.type() == port::unknown) {
      using inputs = vast::format::reader::inputs;
      if constexpr (Reader::defaults::input == inputs::inet) {
        endpoint default_ep;
        vast::parsers::endpoint(Reader::defaults::uri, default_ep);
        ep.port = port{ep.port.number(), default_ep.port.type()};
      } else {
        // Fall back to tcp if we don't know anything else.
        ep.port = port{ep.port.number(), port::tcp};
      }
    }
    Reader reader{slice_type};
    auto run = [&](auto&& source) {
      auto& mm = sys.middleman();
      auto src = mm.spawn_broker(std::forward<decltype(source)>(source),
                                 ep.port.number(), std::move(reader), factory,
                                 slice_size, max_events);
      return source_command(cmd, sys, std::move(src), options, first, last);
    };
    switch (ep.port.type()) {
      default:
        return caf::make_message(
          make_error(vast::ec::unimplemented,
                     "port type not supported:", ep.port.type()));
      case port::udp:
        return run(datagram_source<Reader>);
    }
  } else {
    auto uds = get_or(options, category + ".uds", false);
    auto in = detail::make_input_stream(*file, uds);
    if (!in)
      return caf::make_message(std::move(in.error()));
    Reader reader{slice_type, std::move(*in)};
    auto src = sys.spawn(source<Reader>, std::move(reader), factory, slice_size,
                         max_events);
    return source_command(cmd, sys, std::move(src), options, first, last);
  }
}

} // namespace vast::system
<|endoftext|>


<commit_before>
#ifndef LIBVIDEOGFX_LIBVIDEOGFX_HH
#define LIBVIDEOGFX_LIBVIDEOGFX_HH

#include <libvideogfx/types.hh>
#include <libvideogfx/init.hh>
#include <libvideogfx/error.hh>
#include <libvideogfx/arch/cpu.hh>
#include <libvideogfx/containers/array.hh>
#include <libvideogfx/containers/array2.hh>
#include <libvideogfx/containers/dynarray.hh>
#include <libvideogfx/containers/heap.hh>
#include <libvideogfx/containers/queue.hh>
#include <libvideogfx/graphics/basic/bitmap.hh>
#include <libvideogfx/graphics/basic/image.hh>
#include <libvideogfx/graphics/color/colorspace.hh>
#include <libvideogfx/graphics/color/img2raw.hh>
#include <libvideogfx/graphics/datatypes/primitives.hh>
#include <libvideogfx/graphics/draw/draw.hh>
#include <libvideogfx/graphics/draw/blit.hh>
#include <libvideogfx/graphics/draw/format.hh>
#include <libvideogfx/graphics/draw/pixelops.hh>
#include <libvideogfx/graphics/draw/scale.hh>
#include <libvideogfx/graphics/fileio/jpeg.hh>
#include <libvideogfx/graphics/fileio/mpeg.hh>
#include <libvideogfx/graphics/fileio/ppm.hh>
#include <libvideogfx/graphics/fileio/uyvy.hh>
#include <libvideogfx/graphics/fileio/yuv.hh>
#include <libvideogfx/graphics/fileio/yuv_vqeg.hh>
//#include <libvideogfx/graphics/fileio/avi/aviformat.hh>
#include <libvideogfx/graphics/filters/linear.hh>
//#include <libvideogfx/graphics/filters/nonlin.hh>
#include <libvideogfx/graphics/measure/snr.hh>
//#include <libvideogfx/graphics/visualize/markblks.hh>
//#include <libvideogfx/graphics/visualize/motionfield.hh>
//#include <libvideogfx/graphics/visualize/regions.hh>
//#include <libvideogfx/postscript/image2ps.hh>
//#include <libvideogfx/postscript/layout.hh>
//#include <libvideogfx/postscript/mvfield.hh>
//#include <libvideogfx/postscript/regions.hh>
#include <libvideogfx/utility/bitmanip.hh>
#include <libvideogfx/utility/math.hh>
#include <libvideogfx/utility/refcntr.hh>
#include <libvideogfx/utility/bitstream/bitbuffer.hh>
#include <libvideogfx/utility/bitstream/bitreader.hh>
#include <libvideogfx/utility/bitstream/bitreader_fast.hh>

#ifdef HAVE_X11
#include <libvideogfx/x11/dispimg.hh>
#include <libvideogfx/x11/imgwin.hh>
#include <libvideogfx/x11/server.hh>
#include <libvideogfx/x11/draw_x11.hh>

// #include <libvideogfx/graphics/fileio/v4l_grab.hh>
// #include <libvideogfx/graphics/draw/draw_x11.hh>
#endif

#endif
<commit_msg>added new ImageSink include<commit_after>
#ifndef LIBVIDEOGFX_LIBVIDEOGFX_HH
#define LIBVIDEOGFX_LIBVIDEOGFX_HH

#include <libvideogfx/types.hh>
#include <libvideogfx/init.hh>
#include <libvideogfx/error.hh>
#include <libvideogfx/arch/cpu.hh>
#include <libvideogfx/containers/array.hh>
#include <libvideogfx/containers/array2.hh>
#include <libvideogfx/containers/dynarray.hh>
#include <libvideogfx/containers/heap.hh>
#include <libvideogfx/containers/queue.hh>
#include <libvideogfx/graphics/basic/bitmap.hh>
#include <libvideogfx/graphics/basic/image.hh>
#include <libvideogfx/graphics/color/colorspace.hh>
#include <libvideogfx/graphics/color/img2raw.hh>
#include <libvideogfx/graphics/datatypes/primitives.hh>
#include <libvideogfx/graphics/draw/draw.hh>
#include <libvideogfx/graphics/draw/blit.hh>
#include <libvideogfx/graphics/draw/format.hh>
#include <libvideogfx/graphics/draw/pixelops.hh>
#include <libvideogfx/graphics/draw/scale.hh>
#include <libvideogfx/graphics/fileio/jpeg.hh>
#include <libvideogfx/graphics/fileio/mpeg.hh>
#include <libvideogfx/graphics/fileio/ppm.hh>
#include <libvideogfx/graphics/fileio/uyvy.hh>
#include <libvideogfx/graphics/fileio/yuv.hh>
#include <libvideogfx/graphics/fileio/yuv_vqeg.hh>
#include <libvideogfx/graphics/fileio/imagesink.hh>
//#include <libvideogfx/graphics/fileio/avi/aviformat.hh>
#include <libvideogfx/graphics/filters/linear.hh>
//#include <libvideogfx/graphics/filters/nonlin.hh>
#include <libvideogfx/graphics/measure/snr.hh>
//#include <libvideogfx/graphics/visualize/markblks.hh>
//#include <libvideogfx/graphics/visualize/motionfield.hh>
//#include <libvideogfx/graphics/visualize/regions.hh>
//#include <libvideogfx/postscript/image2ps.hh>
//#include <libvideogfx/postscript/layout.hh>
//#include <libvideogfx/postscript/mvfield.hh>
//#include <libvideogfx/postscript/regions.hh>
#include <libvideogfx/utility/bitmanip.hh>
#include <libvideogfx/utility/math.hh>
#include <libvideogfx/utility/refcntr.hh>
#include <libvideogfx/utility/bitstream/bitbuffer.hh>
#include <libvideogfx/utility/bitstream/bitreader.hh>
#include <libvideogfx/utility/bitstream/bitreader_fast.hh>

#ifdef HAVE_X11
#include <libvideogfx/x11/dispimg.hh>
#include <libvideogfx/x11/imgwin.hh>
#include <libvideogfx/x11/server.hh>
#include <libvideogfx/x11/draw_x11.hh>

// #include <libvideogfx/graphics/fileio/v4l_grab.hh>
// #include <libvideogfx/graphics/draw/draw_x11.hh>
#endif

#endif
<|endoftext|>


<commit_before>// dune-multiscale
// Copyright Holders: Patrick Henning, Rene Milk
// License: BSD 2-Clause License (http://opensource.org/licenses/BSD-2-Clause)

#ifndef DUNE_MS__TOOLS_MISC_HH
#define DUNE_MS__TOOLS_MISC_HH

#include <dune/stuff/common/string.hh>
#include <dune/grid/common/entitypointer.hh>
#include <dune/grid/common/indexidset.hh>

namespace Dune {
namespace Stuff {
namespace Grid {

//!
template < class GridImp, class IteratorImp, class IndexSetImp, class IndexTypeImp>
EntityPointer< const GridImp, IteratorImp > make_father(const IndexSet< GridImp, IndexSetImp, IndexTypeImp >& index_set,
                EntityPointer< const GridImp, IteratorImp > entity )
{
  bool father_found = false;
  auto test_entity = entity;
  while (!father_found)
  {
    if (index_set.contains(*test_entity))
    {
      entity = test_entity;
    }

    if (!test_entity->hasFather())
    {
      father_found = true;
    } else {
      test_entity = test_entity->father();
    }
  }
  return entity;
}

template < class GridImp, class IteratorImp, class IndexSetImp, class IndexTypeImp >
EntityPointer< const GridImp, IteratorImp > make_father(const IndexSet< GridImp, IndexSetImp, IndexTypeImp >& index_set,
                 EntityPointer< const GridImp, IteratorImp > entity,
                 int level_difference)
{
    for (int lev = 0; lev < level_difference; ++lev)
          entity = entity->father();
    return make_father(index_set, entity);
}

template < int cd, int dim,
           template<int,int,class> class EntityImp,
           template<int,int,class> class EntityImpOther,
           class GridImp,
           class GridImpOther>
bool entities_identical(const Entity< cd, dim, GridImp, EntityImp >& entity,
                        const Entity< cd, dim, GridImpOther, EntityImpOther >& other)
{
    const int number_of_nodes = entity.template count< 2 >();
    for (int k = 0; k < number_of_nodes; ++k )
    {
      if ( !( entity.geometry().corner(k) == other.geometry().corner(k) ) )
      {
        return false;
      }
    }
    return true;
}

} // namespace Grid
} // namespace Stuff
} // namespace Dune

#endif // DUNE_MS__TOOLS_MISC_HH
<commit_msg>hopefully fix make_father for all compilers/grid managers<commit_after>// dune-multiscale
// Copyright Holders: Patrick Henning, Rene Milk
// License: BSD 2-Clause License (http://opensource.org/licenses/BSD-2-Clause)

#ifndef DUNE_MS__TOOLS_MISC_HH
#define DUNE_MS__TOOLS_MISC_HH

#include <dune/stuff/common/string.hh>
#include <dune/grid/common/entitypointer.hh>
#include <dune/grid/common/indexidset.hh>

namespace Dune {
namespace Stuff {
namespace Grid {

/** ConstGridImp is supposed to be identical to const GridImp, alas different grid managers
 *  and different type deduction between gcc/clang make two different types necessary here
 */
template < class GridImp, class ConstGridImp, class IteratorImp, class IndexSetImp, class IndexTypeImp>
EntityPointer< GridImp, IteratorImp > make_father(const IndexSet< ConstGridImp, IndexSetImp, IndexTypeImp >& index_set,
                EntityPointer< GridImp, IteratorImp > entity )
{
  bool father_found = false;
  auto test_entity = entity;
  while (!father_found)
  {
    if (index_set.contains(*test_entity))
    {
      entity = test_entity;
    }

    if (!test_entity->hasFather())
    {
      father_found = true;
    } else {
      test_entity = test_entity->father();
    }
  }
  return entity;
}

template < class GridImp, class ConstGridImp, class IteratorImp, class IndexSetImp, class IndexTypeImp >
EntityPointer< GridImp, IteratorImp > make_father(const IndexSet< ConstGridImp, IndexSetImp, IndexTypeImp >& index_set,
                 EntityPointer< GridImp, IteratorImp > entity,
                 int level_difference)
{
    for (int lev = 0; lev < level_difference; ++lev)
          entity = entity->father();
    return make_father(index_set, entity);
}

template < int cd, int dim,
           template<int,int,class> class EntityImp,
           template<int,int,class> class EntityImpOther,
           class GridImp,
           class GridImpOther>
bool entities_identical(const Entity< cd, dim, GridImp, EntityImp >& entity,
                        const Entity< cd, dim, GridImpOther, EntityImpOther >& other)
{
    const int number_of_nodes = entity.template count< 2 >();
    for (int k = 0; k < number_of_nodes; ++k )
    {
      if ( !( entity.geometry().corner(k) == other.geometry().corner(k) ) )
      {
        return false;
      }
    }
    return true;
}

} // namespace Grid
} // namespace Stuff
} // namespace Dune

#endif // DUNE_MS__TOOLS_MISC_HH
<|endoftext|>


<commit_before>#include "glyph_object_creation.hpp"
#include "vector_font.hpp"
#include "text3D.hpp"
#include "object.hpp"

// Include standard headers
#include <stdint.h> // uint32_t etc.
#include <string>   // std::string

namespace yli
{
    namespace ontology
    {
        class Glyph;

        void create_glyph_objects(const std::string& text_string, yli::ontology::Text3D* const text3D)
        {
            const char* text_pointer = text_string.c_str();

            while (*text_pointer != '\0')
            {
                int32_t unicode_value = yli::string::extract_unicode_value_from_string(text_pointer);
                yli::ontology::Glyph* glyph_pointer = text3D->parent->get_glyph_pointer(unicode_value);

                if (glyph_pointer == nullptr)
                {
                    // nullptr, so skip this character.
                    std::cerr << "Error: no matching Glyph found for unicode_value 0x" << std::hex << unicode_value << std::dec << "\n";
                    continue;
                }

                std::cout << "Creating the glyph Object for unicode_value 0x" << std::hex << unicode_value << std::dec << "\n";

                ObjectStruct object_struct;
                object_struct.glyph_parent = glyph_pointer;
                object_struct.text3D_parent = text3D;
                object_struct.original_scale_vector = text3D->original_scale_vector;
                object_struct.rotate_angle = text3D->rotate_angle;
                object_struct.is_character = true;
                object_struct.cartesian_coordinates = text3D->cartesian_coordinates; // TODO: adjust this as needed.
                object_struct.rotate_vector = text3D->rotate_vector;
                yli::ontology::Object* object = new yli::ontology::Object(text3D->universe, object_struct);
            }

            // TODO: Add support for Unicode strings.

            // TODO: go through `text_string`.

            // TODO: extract Unicode.
            //
            // TODO: If the Unicode exists in the hash map, create the corresponding glyph `Object`.
            //       If not, continue from the next Unicode of `text_string`.
        }
    }
}
<commit_msg>Bugfix: added missing `#include` line.<commit_after>#include "glyph_object_creation.hpp"
#include "vector_font.hpp"
#include "text3D.hpp"
#include "object.hpp"
#include "object_struct.hpp"

// Include standard headers
#include <stdint.h> // uint32_t etc.
#include <string>   // std::string

namespace yli
{
    namespace ontology
    {
        class Glyph;

        void create_glyph_objects(const std::string& text_string, yli::ontology::Text3D* const text3D)
        {
            const char* text_pointer = text_string.c_str();

            while (*text_pointer != '\0')
            {
                int32_t unicode_value = yli::string::extract_unicode_value_from_string(text_pointer);
                yli::ontology::Glyph* glyph_pointer = text3D->parent->get_glyph_pointer(unicode_value);

                if (glyph_pointer == nullptr)
                {
                    // nullptr, so skip this character.
                    std::cerr << "Error: no matching Glyph found for unicode_value 0x" << std::hex << unicode_value << std::dec << "\n";
                    continue;
                }

                std::cout << "Creating the glyph Object for unicode_value 0x" << std::hex << unicode_value << std::dec << "\n";

                ObjectStruct object_struct;
                object_struct.glyph_parent = glyph_pointer;
                object_struct.text3D_parent = text3D;
                object_struct.original_scale_vector = text3D->original_scale_vector;
                object_struct.rotate_angle = text3D->rotate_angle;
                object_struct.is_character = true;
                object_struct.cartesian_coordinates = text3D->cartesian_coordinates; // TODO: adjust this as needed.
                object_struct.rotate_vector = text3D->rotate_vector;
                yli::ontology::Object* object = new yli::ontology::Object(text3D->universe, object_struct);
            }

            // TODO: Add support for Unicode strings.

            // TODO: go through `text_string`.

            // TODO: extract Unicode.
            //
            // TODO: If the Unicode exists in the hash map, create the corresponding glyph `Object`.
            //       If not, continue from the next Unicode of `text_string`.
        }
    }
}
<|endoftext|>


<commit_before>//===- CallGraphSort.cpp --------------------------------------------------===//
//
//                             The LLVM Linker
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
///
/// Implementation of Call-Chain Clustering from: Optimizing Function Placement
/// for Large-Scale Data-Center Applications
/// https://research.fb.com/wp-content/uploads/2017/01/cgo2017-hfsort-final1.pdf
///
/// The goal of this algorithm is to improve runtime performance of the final
/// executable by arranging code sections such that page table and i-cache
/// misses are minimized.
///
/// Definitions:
/// * Cluster
///   * An ordered list of input sections which are layed out as a unit. At the
///     beginning of the algorithm each input section has its own cluster and
///     the weight of the cluster is the sum of the weight of all incomming
///     edges.
/// * Call-Chain Clustering (C³) Heuristic
///   * Defines when and how clusters are combined. Pick the highest weighted
///     input section then add it to its most likely predecessor if it wouldn't
///     penalize it too much.
/// * Density
///   * The weight of the cluster divided by the size of the cluster. This is a
///     proxy for the ammount of execution time spent per byte of the cluster.
///
/// It does so given a call graph profile by the following:
/// * Build a weighted call graph from the call graph profile
/// * Sort input sections by weight
/// * For each input section starting with the highest weight
///   * Find its most likely predecessor cluster
///   * Check if the combined cluster would be too large, or would have too low
///     a density.
///   * If not, then combine the clusters.
/// * Sort non-empty clusters by density
///
//===----------------------------------------------------------------------===//

#include "CallGraphSort.h"
#include "OutputSections.h"
#include "SymbolTable.h"
#include "Symbols.h"

using namespace llvm;
using namespace lld;
using namespace lld::elf;

namespace {
struct Edge {
  int From;
  uint64_t Weight;
};

struct Cluster {
  Cluster(int Sec, size_t S) {
    Sections.push_back(Sec);
    Size = S;
  }

  double getDensity() const {
    if (Size == 0)
      return 0;
    return double(Weight) / double(Size);
  }

  std::vector<int> Sections;
  size_t Size = 0;
  uint64_t Weight = 0;
  uint64_t InitialWeight = 0;
  std::vector<Edge> Preds;
};

class CallGraphSort {
public:
  CallGraphSort();

  DenseMap<const InputSectionBase *, int> run();

private:
  std::vector<Cluster> Clusters;
  std::vector<const InputSectionBase *> Sections;

  void groupClusters();
};

// Maximum ammount the combined cluster density can be worse than the original
// cluster to consider merging.
constexpr int MAX_DENSITY_DEGRADATION = 8;

// Maximum cluster size in bytes.
constexpr uint64_t MAX_CLUSTER_SIZE = 1024 * 1024;
} // end anonymous namespace

// Take the edge list in Config->CallGraphProfile, resolve symbol names to
// Symbols, and generate a graph between InputSections with the provided
// weights.
CallGraphSort::CallGraphSort() {
  llvm::MapVector<std::pair<const InputSectionBase *, const InputSectionBase *>,
                  uint64_t> &Profile = Config->CallGraphProfile;
  DenseMap<const InputSectionBase *, int> SecToCluster;

  auto GetOrCreateNode = [&](const InputSectionBase *IS) -> int {
    auto Res = SecToCluster.insert(std::make_pair(IS, Clusters.size()));
    if (Res.second) {
      Sections.push_back(IS);
      Clusters.emplace_back(Clusters.size(), IS->getSize());
    }
    return Res.first->second;
  };

  // Create the graph.
  for (const auto &C : Profile) {
    const auto *FromSB = cast<InputSectionBase>(C.first.first->Repl);
    const auto *ToSB = cast<InputSectionBase>(C.first.second->Repl);
    uint64_t Weight = C.second;

    // Ignore edges between input sections belonging to different output
    // sections.  This is done because otherwise we would end up with clusters
    // containing input sections that can't actually be placed adjacently in the
    // output.  This messes with the cluster size and density calculations.  We
    // would also end up moving input sections in other output sections without
    // moving them closer to what calls them.
    if (FromSB->getOutputSection() != ToSB->getOutputSection())
      continue;

    int From = GetOrCreateNode(FromSB);
    int To = GetOrCreateNode(ToSB);

    Clusters[To].Weight += Weight;

    if (From == To)
      continue;

    // Add an edge
    Clusters[To].Preds.push_back({From, Weight});
  }
  for (Cluster &C : Clusters)
    C.InitialWeight = C.Weight;
}

// It's bad to merge clusters which would degrade the density too much.
static bool isNewDensityBad(Cluster &A, Cluster &B) {
  double NewDensity = double(A.Weight + B.Weight) / double(A.Size + B.Size);
  if (NewDensity < A.getDensity() / MAX_DENSITY_DEGRADATION)
    return true;
  return false;
}

static void mergeClusters(Cluster &Into, Cluster &From) {
  Into.Sections.insert(Into.Sections.end(), From.Sections.begin(),
                       From.Sections.end());
  Into.Size += From.Size;
  Into.Weight += From.Weight;
  From.Sections.clear();
  From.Size = 0;
  From.Weight = 0;
}

// Group InputSections into clusters using the Call-Chain Clustering heuristic
// then sort the clusters by density.
void CallGraphSort::groupClusters() {
  std::vector<int> SortedSecs(Clusters.size());
  std::vector<Cluster *> SecToCluster(Clusters.size());

  for (size_t I = 0; I < Clusters.size(); ++I) {
    SortedSecs[I] = I;
    SecToCluster[I] = &Clusters[I];
  }

  std::stable_sort(SortedSecs.begin(), SortedSecs.end(), [&](int A, int B) {
    return Clusters[B].getDensity() < Clusters[A].getDensity();
  });

  for (int SI : SortedSecs) {
    // Clusters[SI] is the same as SecToClusters[SI] here because it has not
    // been merged into another cluster yet.
    Cluster &C = Clusters[SI];

    int BestPred = -1;
    uint64_t BestWeight = 0;

    for (Edge &E : C.Preds) {
      if (BestPred == -1 || E.Weight > BestWeight) {
        BestPred = E.From;
        BestWeight = E.Weight;
      }
    }

    // don't consider merging if the edge is unlikely.
    if (BestWeight * 10 <= C.InitialWeight)
      continue;

    Cluster *PredC = SecToCluster[BestPred];
    if (PredC == &C)
      continue;

    if (C.Size + PredC->Size > MAX_CLUSTER_SIZE)
      continue;

    if (isNewDensityBad(*PredC, C))
      continue;

    // NOTE: Consider using a disjoint-set to track section -> cluster mapping
    // if this is ever slow.
    for (int SI : C.Sections)
      SecToCluster[SI] = PredC;

    mergeClusters(*PredC, C);
  }

  // Remove empty or dead nodes. Invalidates all cluster indices.
  llvm::erase_if(Clusters, [](const Cluster &C) {
    return C.Size == 0 || C.Sections.empty();
  });

  // Sort by density.
  std::stable_sort(Clusters.begin(), Clusters.end(),
                   [](const Cluster &A, const Cluster &B) {
                     return A.getDensity() > B.getDensity();
                   });
}

DenseMap<const InputSectionBase *, int> CallGraphSort::run() {
  groupClusters();

  // Generate order.
  llvm::DenseMap<const InputSectionBase *, int> OrderMap;
  ssize_t CurOrder = 1;

  for (const Cluster &C : Clusters)
    for (int SecIndex : C.Sections)
      OrderMap[Sections[SecIndex]] = CurOrder++;

  return OrderMap;
}

// Sort sections by the profile data provided by -callgraph-profile-file
//
// This first builds a call graph based on the profile data then merges sections
// according to the C³ huristic. All clusters are then sorted by a density
// metric to further improve locality.
DenseMap<const InputSectionBase *, int> elf::computeCallGraphProfileOrder() {
  return CallGraphSort().run();
}
<commit_msg>[LLD][ELF] - Simplify Call-Chain Clustering implementation a bit.<commit_after>//===- CallGraphSort.cpp --------------------------------------------------===//
//
//                             The LLVM Linker
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
///
/// Implementation of Call-Chain Clustering from: Optimizing Function Placement
/// for Large-Scale Data-Center Applications
/// https://research.fb.com/wp-content/uploads/2017/01/cgo2017-hfsort-final1.pdf
///
/// The goal of this algorithm is to improve runtime performance of the final
/// executable by arranging code sections such that page table and i-cache
/// misses are minimized.
///
/// Definitions:
/// * Cluster
///   * An ordered list of input sections which are layed out as a unit. At the
///     beginning of the algorithm each input section has its own cluster and
///     the weight of the cluster is the sum of the weight of all incomming
///     edges.
/// * Call-Chain Clustering (C³) Heuristic
///   * Defines when and how clusters are combined. Pick the highest weighted
///     input section then add it to its most likely predecessor if it wouldn't
///     penalize it too much.
/// * Density
///   * The weight of the cluster divided by the size of the cluster. This is a
///     proxy for the ammount of execution time spent per byte of the cluster.
///
/// It does so given a call graph profile by the following:
/// * Build a weighted call graph from the call graph profile
/// * Sort input sections by weight
/// * For each input section starting with the highest weight
///   * Find its most likely predecessor cluster
///   * Check if the combined cluster would be too large, or would have too low
///     a density.
///   * If not, then combine the clusters.
/// * Sort non-empty clusters by density
///
//===----------------------------------------------------------------------===//

#include "CallGraphSort.h"
#include "OutputSections.h"
#include "SymbolTable.h"
#include "Symbols.h"

using namespace llvm;
using namespace lld;
using namespace lld::elf;

namespace {
struct Edge {
  int From;
  uint64_t Weight;
};

struct Cluster {
  Cluster(int Sec, size_t S) {
    Sections.push_back(Sec);
    Size = S;
  }

  double getDensity() const {
    if (Size == 0)
      return 0;
    return double(Weight) / double(Size);
  }

  std::vector<int> Sections;
  size_t Size = 0;
  uint64_t Weight = 0;
  uint64_t InitialWeight = 0;
  Edge BestPred = {-1, 0};
};

class CallGraphSort {
public:
  CallGraphSort();

  DenseMap<const InputSectionBase *, int> run();

private:
  std::vector<Cluster> Clusters;
  std::vector<const InputSectionBase *> Sections;

  void groupClusters();
};

// Maximum ammount the combined cluster density can be worse than the original
// cluster to consider merging.
constexpr int MAX_DENSITY_DEGRADATION = 8;

// Maximum cluster size in bytes.
constexpr uint64_t MAX_CLUSTER_SIZE = 1024 * 1024;
} // end anonymous namespace

// Take the edge list in Config->CallGraphProfile, resolve symbol names to
// Symbols, and generate a graph between InputSections with the provided
// weights.
CallGraphSort::CallGraphSort() {
  llvm::MapVector<std::pair<const InputSectionBase *, const InputSectionBase *>,
                  uint64_t> &Profile = Config->CallGraphProfile;
  DenseMap<const InputSectionBase *, int> SecToCluster;

  auto GetOrCreateNode = [&](const InputSectionBase *IS) -> int {
    auto Res = SecToCluster.insert(std::make_pair(IS, Clusters.size()));
    if (Res.second) {
      Sections.push_back(IS);
      Clusters.emplace_back(Clusters.size(), IS->getSize());
    }
    return Res.first->second;
  };

  // Create the graph.
  for (const auto &C : Profile) {
    const auto *FromSB = cast<InputSectionBase>(C.first.first->Repl);
    const auto *ToSB = cast<InputSectionBase>(C.first.second->Repl);
    uint64_t Weight = C.second;

    // Ignore edges between input sections belonging to different output
    // sections.  This is done because otherwise we would end up with clusters
    // containing input sections that can't actually be placed adjacently in the
    // output.  This messes with the cluster size and density calculations.  We
    // would also end up moving input sections in other output sections without
    // moving them closer to what calls them.
    if (FromSB->getOutputSection() != ToSB->getOutputSection())
      continue;

    int From = GetOrCreateNode(FromSB);
    int To = GetOrCreateNode(ToSB);

    Clusters[To].Weight += Weight;

    if (From == To)
      continue;

    // Remember the best edge.
    Cluster &ToC = Clusters[To];
    if (ToC.BestPred.From == -1 || ToC.BestPred.Weight < Weight) {
      ToC.BestPred.From = From;
      ToC.BestPred.Weight = Weight;
    }
  }
  for (Cluster &C : Clusters)
    C.InitialWeight = C.Weight;
}

// It's bad to merge clusters which would degrade the density too much.
static bool isNewDensityBad(Cluster &A, Cluster &B) {
  double NewDensity = double(A.Weight + B.Weight) / double(A.Size + B.Size);
  if (NewDensity < A.getDensity() / MAX_DENSITY_DEGRADATION)
    return true;
  return false;
}

static void mergeClusters(Cluster &Into, Cluster &From) {
  Into.Sections.insert(Into.Sections.end(), From.Sections.begin(),
                       From.Sections.end());
  Into.Size += From.Size;
  Into.Weight += From.Weight;
  From.Sections.clear();
  From.Size = 0;
  From.Weight = 0;
}

// Group InputSections into clusters using the Call-Chain Clustering heuristic
// then sort the clusters by density.
void CallGraphSort::groupClusters() {
  std::vector<int> SortedSecs(Clusters.size());
  std::vector<Cluster *> SecToCluster(Clusters.size());

  for (size_t I = 0; I < Clusters.size(); ++I) {
    SortedSecs[I] = I;
    SecToCluster[I] = &Clusters[I];
  }

  std::stable_sort(SortedSecs.begin(), SortedSecs.end(), [&](int A, int B) {
    return Clusters[B].getDensity() < Clusters[A].getDensity();
  });

  for (int SI : SortedSecs) {
    // Clusters[SI] is the same as SecToClusters[SI] here because it has not
    // been merged into another cluster yet.
    Cluster &C = Clusters[SI];

    // Don't consider merging if the edge is unlikely.
    if (C.BestPred.From == -1 || C.BestPred.Weight * 10 <= C.InitialWeight)
      continue;

    Cluster *PredC = SecToCluster[C.BestPred.From];
    if (PredC == &C)
      continue;

    if (C.Size + PredC->Size > MAX_CLUSTER_SIZE)
      continue;

    if (isNewDensityBad(*PredC, C))
      continue;

    // NOTE: Consider using a disjoint-set to track section -> cluster mapping
    // if this is ever slow.
    for (int SI : C.Sections)
      SecToCluster[SI] = PredC;

    mergeClusters(*PredC, C);
  }

  // Remove empty or dead nodes. Invalidates all cluster indices.
  llvm::erase_if(Clusters, [](const Cluster &C) {
    return C.Size == 0 || C.Sections.empty();
  });

  // Sort by density.
  std::stable_sort(Clusters.begin(), Clusters.end(),
                   [](const Cluster &A, const Cluster &B) {
                     return A.getDensity() > B.getDensity();
                   });
}

DenseMap<const InputSectionBase *, int> CallGraphSort::run() {
  groupClusters();

  // Generate order.
  llvm::DenseMap<const InputSectionBase *, int> OrderMap;
  ssize_t CurOrder = 1;

  for (const Cluster &C : Clusters)
    for (int SecIndex : C.Sections)
      OrderMap[Sections[SecIndex]] = CurOrder++;

  return OrderMap;
}

// Sort sections by the profile data provided by -callgraph-profile-file
//
// This first builds a call graph based on the profile data then merges sections
// according to the C³ huristic. All clusters are then sorted by a density
// metric to further improve locality.
DenseMap<const InputSectionBase *, int> elf::computeCallGraphProfileOrder() {
  return CallGraphSort().run();
}
<|endoftext|>


<commit_before><commit_msg>Test for `Material::bind_to_new_parent`.<commit_after><|endoftext|>


<commit_before>// $Id$
// -*-C++-*-
// * BeginRiceCopyright *****************************************************
//
// Copyright ((c)) 2002, Rice University
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
//   notice, this list of conditions and the following disclaimer.
//
// * Redistributions in binary form must reproduce the above copyright
//   notice, this list of conditions and the following disclaimer in the
//   documentation and/or other materials provided with the distribution.
//
// * Neither the name of Rice University (RICE) nor the names of its
//   contributors may be used to endorse or promote products derived from
//   this software without specific prior written permission.
//
// This software is provided by RICE 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 RICE 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.
//
// ******************************************************* EndRiceCopyright *

//***************************************************************************
//
// File:
//    String.h
//
// Purpose:
//    [A brief statement of the purpose of the file.]
//
// Description:
//    [The set of functions, macros, etc. defined in the file]
//
// History:
//    950920 - curetonk - initial revision
//
//***************************************************************************

#ifndef String_h
#define String_h

//************************** System Include Files ***************************

#ifdef NO_STD_CHEADERS
# include <string.h>
# include <ctype.h>
#else
# include <cstring>
using std::strlen; // For compatibility with non-std C headers
using std::strcpy;
using std::strcmp;
using std::strncmp;
using std::strerror;
using std::strtok;
using std::memset;
using std::memcpy;
using std::size_t;
# include <cctype>
using std::isdigit; // For compatibility with non-std C headers
#endif

//*************************** User Include Files ****************************

#include <include/general.h>

//************************ Enumeration Definitions **************************

//***************************************************************************
//
//  Enumeration:
//     StringStripLocation
//
//  Enumeration Members:
//     StringStripLeading  - strip leading whitespace.
//     StringStripTrailing - strip trailing whitespace.
//     StringStripBoth     - strip leading and trailing whitespace.
//     StringStripAll      - strip all whitespace.
//
//  Purpose:
//     Determine what whitespace to remove from the string.
//
//  History:
//     950920 - curetonk - initial revision
//
//***************************************************************************
enum StringStripLocation
{
   StringStripLeading,
   StringStripTrailing,
   StringStripBoth,
   StringStripAll
};

//***************************************************************************
//
//  Enumeration:
//     StringSearchDirection
//
//  Enumeration Members:
//     StringSearchForward  - search from position to end of string.
//     StringSearchBackward - search from position to beginning of string.
//
//  Purpose:
//     The direction in which to search the string.
//
//  History:
//     950920 - curetonk - initial revision
//
//***************************************************************************
enum StringSearchDirection
{
   StringSearchForward,
   StringSearchBackward
};

//***************************************************************************
//
//  Enumeration:
//     StringInclusive
//
//  Enumeration Members:
//     enumName1 -  description of enumName1
//     enumName2 -  description of enumName2
//
//  Purpose:
//     [The purpose of the enumeration, i.e., what it is used for.]
//
//  History:
//     950920 - curetonk - initial revision
//
//***************************************************************************
enum StringInclusive
{
   StringOf,
   StringNotOf
};

//**************************** Class Definitions ****************************

//***************************************************************************
//
//  Class:
//     String
//
//  Base Classes:
//     none
//
//  Class Data Members:
//     char* stringText (private) - the character string.
//     unsigned int stringSize (private) - the size of the character string.
//
//  Purpose:
//
//  History:
//     950920 - curetonk - initial revision adapted from code found on
//                         the internet.
//
//***************************************************************************
class String
{
   public:
      static const int UNKNOWN_POSITION;
        // A position return value that indicates not found.

      static const unsigned int MAX_SIZE;
        // A hypothetical maximum String size.

      //----------------------------------------
      // Constructors
      //----------------------------------------
      String(const char* newString = "", int theLength = UNKNOWN_POSITION);
        // Construct String from a known C-string and an optional length.
        // Note that this is the default constructor.

      String(char aChar);
        // Construct from a single character.

      String(const char* string1, const char* string2);
        // Construct from a pair of C-strings.

      String(char fillChar, unsigned int length);
        // Construct from a replicated character.

      String(double d);
        // construct from double

      String(long i);
        // construct from int/long value

      String(unsigned long i, bool hex = false);
        // construct from unsigned long value (setting 'hex' converts
        // to hex representation, (e.g. pointer))

#ifdef ARCH_USE_LONG_LONG // FIXME
      String(long long i);
      String(unsigned long long i, bool hex = false);
#endif

      String(const String& copyString);
        // Copy constructor.

      //----------------------------------------
      // Destructor
      //----------------------------------------
      ~String( );

      //----------------------------------------
      // NULL test ("" is the empty string)
      //----------------------------------------
      bool Empty() const { return (stringText[0] == '\0'); }

      //----------------------------------------
      // Size related functions
      //----------------------------------------
      unsigned int Length() const;
      void Resize(unsigned int newSize);
      unsigned int Size() const;

      //----------------------------------------
      // Formatting
      //----------------------------------------
      void LeftFormat(int width);
      void RightFormat(int width);

      //----------------------------------------
      // Case conversion - returns a new string
      //----------------------------------------
      String ToUpper() const;
      String ToLower() const;

      //----------------------------------------
      // Positional operator
      //----------------------------------------
      // Return the (read-only) character in the string at a given offset.
      char operator[] (unsigned int position) const;

      // Return the (modifiable) character in the string at a given offset.
      char& operator[] (unsigned int position);

      //----------------------------------------
      // Type conversion
      //----------------------------------------
      operator const char*() const;

      //----------------------------------------
      // Assignment operators
      //----------------------------------------
      // Assign to this.
      String& operator=(const String& theString);
      String& operator=(const char* charString);
      String& operator=(char aChar);

      // Append another string to this.
      String& operator+=(const String& theString);
      String& operator+=(const char* charString);
      String& operator+=(char aChar);

      // Concatenate two strings - returns a new string
      friend String operator+(const String& s1, const String& s2);
      friend String operator+(const String& s1, const char* charString);

      //----------------------------------------
      // Relational operators
      //----------------------------------------

      // Compare two strings for equality.
      friend bool operator==(const String& s1, const String& s2);
      friend bool operator==(const String& s1, const char* charString);

      // Compare two strings for inequality.
      friend bool operator!=(const String& s1, const String& s2);
      friend bool operator!=(const String& s1, const char* charString);

      // Compare two strings for exclusive alphanumeric precedence.
      friend bool operator<(const String& s1, const String& theString);
      friend bool operator<(const String& s1, const char* charString);

      // Compare two strings for exclusive alphanumeric antecedence.
      friend bool operator>(const String& s1, const String& s2);
      friend bool operator>(const String& s1, const char* charString);

      // Compare two strings for inclusive alphanumeric precedence.
      friend bool operator<=(const String& s1, const String& s2);
      friend bool operator<=(const String& s1, const char* charString);

      // Compare two strings for inclusive alphanumeric antecedence.
      friend bool operator>=(const String& s1, const String& s2);
      friend bool operator>=(const String& s1, const char* charString);

      //----------------------------------------
      // Searching
      //----------------------------------------
      // Find the position of the target substring within this string.
      int FindSubstring(const char* target,
                        StringSearchDirection direction = StringSearchForward,
                        unsigned int startPosition = 0) const;

      // Find the position of any character in the target string.
      int FindChar(const char* target,
                   StringInclusive isOf = StringOf,
                   StringSearchDirection direction = StringSearchForward,
                   unsigned int startPosition = 0) const;
      int FindChar(char target,
                   StringInclusive isOf = StringOf,
                   StringSearchDirection direction = StringSearchForward,
                   unsigned int startPosition = 0) const;

      //----------------------------------------
      // Editing
      //----------------------------------------
      // Insert the new string into this at the given position.
      String& Insert(const char* charString, unsigned int insertPosition);

      // Remove size characters starting with the position.
      String& Remove(unsigned int removePosition,
                     unsigned int removeSize = MAX_SIZE);

      // Replace size characters with the new string.
      String& Replace(const char* charString,
                      unsigned int replacePosition,
                      unsigned int replaceSize);

      // Remove the given characters from the given location.
      // We default to stripping leading and trailing whitespace.
      String& Strip(StringStripLocation s = StringStripBoth,
                    const char* sTarget = " \t");

      //----------------------------------------
      // Dumping
      //----------------------------------------
      void Dump(const char* indent = "") const;

   protected:
      char* stringText;
      unsigned int stringSize;
      void VerifySizeForLength(unsigned int length, bool keep);
      static bool CharIsOfString(char aChar, const char* buffer);
};

// ****************************************************************************
// classes/fcts/methods necessary for STL templates
class StringLt {
public:
  // strict (less-than) operator for Strings
  int operator()(const String& s1, const String& s2 ) const
    { return s1 < s2; }
};

class StringEq {
public:
  // strict comparison (equal) operator for Strings
  int operator()(const String& s1, const String& s2 ) const
    { return s1 == s2; }
};

extern size_t HashString(const String &s);

class StringHash {
public:
  // strict comparison (equal) operator for Strings
  size_t operator()(const String& s) const {
    return HashString(s);
  }
};

#endif
<commit_msg>Ensure strchr() is visible within the default namespace.<commit_after>// $Id$
// -*-C++-*-
// * BeginRiceCopyright *****************************************************
//
// Copyright ((c)) 2002, Rice University
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
//   notice, this list of conditions and the following disclaimer.
//
// * Redistributions in binary form must reproduce the above copyright
//   notice, this list of conditions and the following disclaimer in the
//   documentation and/or other materials provided with the distribution.
//
// * Neither the name of Rice University (RICE) nor the names of its
//   contributors may be used to endorse or promote products derived from
//   this software without specific prior written permission.
//
// This software is provided by RICE 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 RICE 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.
//
// ******************************************************* EndRiceCopyright *

//***************************************************************************
//
// File:
//    String.h
//
// Purpose:
//    [A brief statement of the purpose of the file.]
//
// Description:
//    [The set of functions, macros, etc. defined in the file]
//
// History:
//    950920 - curetonk - initial revision
//
//***************************************************************************

#ifndef String_h
#define String_h

//************************** System Include Files ***************************

#ifdef NO_STD_CHEADERS
# include <string.h>
# include <ctype.h>
#else
# include <cstring>
using std::strlen; // For compatibility with non-std C headers
using std::strcpy;
using std::strcmp;
using std::strncmp;
using std::strerror;
using std::strtok;
using std::strchr;
using std::memset;
using std::memcpy;
using std::size_t;
# include <cctype>
using std::isdigit; // For compatibility with non-std C headers
#endif

//*************************** User Include Files ****************************

#include <include/general.h>

//************************ Enumeration Definitions **************************

//***************************************************************************
//
//  Enumeration:
//     StringStripLocation
//
//  Enumeration Members:
//     StringStripLeading  - strip leading whitespace.
//     StringStripTrailing - strip trailing whitespace.
//     StringStripBoth     - strip leading and trailing whitespace.
//     StringStripAll      - strip all whitespace.
//
//  Purpose:
//     Determine what whitespace to remove from the string.
//
//  History:
//     950920 - curetonk - initial revision
//
//***************************************************************************
enum StringStripLocation
{
   StringStripLeading,
   StringStripTrailing,
   StringStripBoth,
   StringStripAll
};

//***************************************************************************
//
//  Enumeration:
//     StringSearchDirection
//
//  Enumeration Members:
//     StringSearchForward  - search from position to end of string.
//     StringSearchBackward - search from position to beginning of string.
//
//  Purpose:
//     The direction in which to search the string.
//
//  History:
//     950920 - curetonk - initial revision
//
//***************************************************************************
enum StringSearchDirection
{
   StringSearchForward,
   StringSearchBackward
};

//***************************************************************************
//
//  Enumeration:
//     StringInclusive
//
//  Enumeration Members:
//     enumName1 -  description of enumName1
//     enumName2 -  description of enumName2
//
//  Purpose:
//     [The purpose of the enumeration, i.e., what it is used for.]
//
//  History:
//     950920 - curetonk - initial revision
//
//***************************************************************************
enum StringInclusive
{
   StringOf,
   StringNotOf
};

//**************************** Class Definitions ****************************

//***************************************************************************
//
//  Class:
//     String
//
//  Base Classes:
//     none
//
//  Class Data Members:
//     char* stringText (private) - the character string.
//     unsigned int stringSize (private) - the size of the character string.
//
//  Purpose:
//
//  History:
//     950920 - curetonk - initial revision adapted from code found on
//                         the internet.
//
//***************************************************************************
class String
{
   public:
      static const int UNKNOWN_POSITION;
        // A position return value that indicates not found.

      static const unsigned int MAX_SIZE;
        // A hypothetical maximum String size.

      //----------------------------------------
      // Constructors
      //----------------------------------------
      String(const char* newString = "", int theLength = UNKNOWN_POSITION);
        // Construct String from a known C-string and an optional length.
        // Note that this is the default constructor.

      String(char aChar);
        // Construct from a single character.

      String(const char* string1, const char* string2);
        // Construct from a pair of C-strings.

      String(char fillChar, unsigned int length);
        // Construct from a replicated character.

      String(double d);
        // construct from double

      String(long i);
        // construct from int/long value

      String(unsigned long i, bool hex = false);
        // construct from unsigned long value (setting 'hex' converts
        // to hex representation, (e.g. pointer))

#ifdef ARCH_USE_LONG_LONG // FIXME
      String(long long i);
      String(unsigned long long i, bool hex = false);
#endif

      String(const String& copyString);
        // Copy constructor.

      //----------------------------------------
      // Destructor
      //----------------------------------------
      ~String( );

      //----------------------------------------
      // NULL test ("" is the empty string)
      //----------------------------------------
      bool Empty() const { return (stringText[0] == '\0'); }

      //----------------------------------------
      // Size related functions
      //----------------------------------------
      unsigned int Length() const;
      void Resize(unsigned int newSize);
      unsigned int Size() const;

      //----------------------------------------
      // Formatting
      //----------------------------------------
      void LeftFormat(int width);
      void RightFormat(int width);

      //----------------------------------------
      // Case conversion - returns a new string
      //----------------------------------------
      String ToUpper() const;
      String ToLower() const;

      //----------------------------------------
      // Positional operator
      //----------------------------------------
      // Return the (read-only) character in the string at a given offset.
      char operator[] (unsigned int position) const;

      // Return the (modifiable) character in the string at a given offset.
      char& operator[] (unsigned int position);

      //----------------------------------------
      // Type conversion
      //----------------------------------------
      operator const char*() const;

      //----------------------------------------
      // Assignment operators
      //----------------------------------------
      // Assign to this.
      String& operator=(const String& theString);
      String& operator=(const char* charString);
      String& operator=(char aChar);

      // Append another string to this.
      String& operator+=(const String& theString);
      String& operator+=(const char* charString);
      String& operator+=(char aChar);

      // Concatenate two strings - returns a new string
      friend String operator+(const String& s1, const String& s2);
      friend String operator+(const String& s1, const char* charString);

      //----------------------------------------
      // Relational operators
      //----------------------------------------

      // Compare two strings for equality.
      friend bool operator==(const String& s1, const String& s2);
      friend bool operator==(const String& s1, const char* charString);

      // Compare two strings for inequality.
      friend bool operator!=(const String& s1, const String& s2);
      friend bool operator!=(const String& s1, const char* charString);

      // Compare two strings for exclusive alphanumeric precedence.
      friend bool operator<(const String& s1, const String& theString);
      friend bool operator<(const String& s1, const char* charString);

      // Compare two strings for exclusive alphanumeric antecedence.
      friend bool operator>(const String& s1, const String& s2);
      friend bool operator>(const String& s1, const char* charString);

      // Compare two strings for inclusive alphanumeric precedence.
      friend bool operator<=(const String& s1, const String& s2);
      friend bool operator<=(const String& s1, const char* charString);

      // Compare two strings for inclusive alphanumeric antecedence.
      friend bool operator>=(const String& s1, const String& s2);
      friend bool operator>=(const String& s1, const char* charString);

      //----------------------------------------
      // Searching
      //----------------------------------------
      // Find the position of the target substring within this string.
      int FindSubstring(const char* target,
                        StringSearchDirection direction = StringSearchForward,
                        unsigned int startPosition = 0) const;

      // Find the position of any character in the target string.
      int FindChar(const char* target,
                   StringInclusive isOf = StringOf,
                   StringSearchDirection direction = StringSearchForward,
                   unsigned int startPosition = 0) const;
      int FindChar(char target,
                   StringInclusive isOf = StringOf,
                   StringSearchDirection direction = StringSearchForward,
                   unsigned int startPosition = 0) const;

      //----------------------------------------
      // Editing
      //----------------------------------------
      // Insert the new string into this at the given position.
      String& Insert(const char* charString, unsigned int insertPosition);

      // Remove size characters starting with the position.
      String& Remove(unsigned int removePosition,
                     unsigned int removeSize = MAX_SIZE);

      // Replace size characters with the new string.
      String& Replace(const char* charString,
                      unsigned int replacePosition,
                      unsigned int replaceSize);

      // Remove the given characters from the given location.
      // We default to stripping leading and trailing whitespace.
      String& Strip(StringStripLocation s = StringStripBoth,
                    const char* sTarget = " \t");

      //----------------------------------------
      // Dumping
      //----------------------------------------
      void Dump(const char* indent = "") const;

   protected:
      char* stringText;
      unsigned int stringSize;
      void VerifySizeForLength(unsigned int length, bool keep);
      static bool CharIsOfString(char aChar, const char* buffer);
};

// ****************************************************************************
// classes/fcts/methods necessary for STL templates
class StringLt {
public:
  // strict (less-than) operator for Strings
  int operator()(const String& s1, const String& s2 ) const
    { return s1 < s2; }
};

class StringEq {
public:
  // strict comparison (equal) operator for Strings
  int operator()(const String& s1, const String& s2 ) const
    { return s1 == s2; }
};

extern size_t HashString(const String &s);

class StringHash {
public:
  // strict comparison (equal) operator for Strings
  size_t operator()(const String& s) const {
    return HashString(s);
  }
};

#endif
<|endoftext|>


<commit_before>// Time:  O(nlogn)
// Space: O(n)

class Solution {
public:
    enum {start, end, height};
    /**
     * @param buildings: A list of lists of integers
     * @return: Find the outline of those buildings
     */
    vector<vector<int> > buildingOutline(vector<vector<int> > &buildings) {
        return ComputeSkylineInInterval(buildings, 0, buildings.size());
    }

    // Divide and Conquer.
    vector<vector<int>> ComputeSkylineInInterval(const vector<vector<int>>& buildings,
                                                 int left_endpoint, int right_endpoint) {
        if (right_endpoint - left_endpoint <= 1) {  // 0 or 1 skyline, just copy it.
            return {buildings.cbegin() + left_endpoint,
                buildings.cbegin() + right_endpoint};
        }
        int mid = left_endpoint + ((right_endpoint - left_endpoint) / 2);
        auto left_skyline = ComputeSkylineInInterval(buildings, left_endpoint, mid);
        auto right_skyline = ComputeSkylineInInterval(buildings, mid, right_endpoint);
        return MergeSkylines(left_skyline, right_skyline);
    }

    // Merge Sort
    vector<vector<int>> MergeSkylines(vector<vector<int>>& left_skyline, vector<vector<int>>& right_skyline) {
        int i = 0, j = 0;
        vector<vector<int>> merged;

        while (i < left_skyline.size() && j < right_skyline.size()) {
            if (left_skyline[i][end] < right_skyline[j][start]) {
                merged.emplace_back(left_skyline[i++]);
            } else if (right_skyline[j][end] < left_skyline[i][start]) {
                merged.emplace_back(right_skyline[j++]);
            } else if (left_skyline[i][start] <= right_skyline[j][start]) {
                MergeIntersectSkylines(merged, left_skyline[i], i,
                                       right_skyline[j], j);
            } else {  // left_skyline[i][start] > right_skyline[j][start].
                MergeIntersectSkylines(merged, right_skyline[j], j,
                                       left_skyline[i], i);
            }
        }

        // Insert the remaining skylines.
        merged.insert(merged.end(), left_skyline.begin() + i, left_skyline.end());
        merged.insert(merged.end(), right_skyline.begin() + j, right_skyline.end());
        return merged;
    }

    // a[start] <= b[start]
    void MergeIntersectSkylines(vector<vector<int>>& merged, vector<int>& a, int& a_idx,
                                vector<int>& b, int& b_idx) {
        if (a[end] <= b[end]) {
            if (a[height] > b[height]) {  // |aaa|
                if (b[end] != a[end]) {   // |abb|b
                    merged.emplace_back(a), ++a_idx;
                    b[start] = a[end];
                } else {        // aaa
                    ++b_idx;    // abb
                }
            } else if (a[height] == b[height]) { // abb
                b[start] = a[start], ++a_idx;    // abb
            } else {  // a[height] < b[height].
                if (a[start] != b[start]) {                                           //    bb
                    merged.emplace_back(vector<int>{a[start], b[start], a[height]});  // |a|bb
                }
                ++a_idx;
            }
        } else {  // a[end] > b[end].
            if (a[height] >= b[height]) {  // aaaa
                ++b_idx;                   // abba
            } else {
                //    |bb|
                // |a||bb|a
                if (a[start] != b[start]) {
                    merged.emplace_back(vector<int>{a[start], b[start], a[height]});
                }
                a[start] = b[end];
                merged.emplace_back(b), ++b_idx;
            }
        }
    }
};

// Time:  O(nlogn)
// Space: O(n)
class Solution2 {
public:
    /**
     * @param buildings: A list of lists of integers
     * @return: Find the outline of those buildings
     */
    vector<vector<int> > buildingOutline(vector<vector<int> > &buildings) {
        unordered_map<int, vector<int>> start_point_to_heights;
        unordered_map<int, vector<int>> end_point_to_heights;
        set<int> points;

        for (int i = 0; i < buildings.size(); ++i) {
            start_point_to_heights[buildings[i][0]].push_back(buildings[i][2]);
            end_point_to_heights[buildings[i][1]].push_back(buildings[i][2]);
            points.emplace(buildings[i][0]);
            points.emplace(buildings[i][1]);
        }

        vector<vector<int>> res;
        map<int, int> height_to_count;
        int curr_start = -1;
        int curr_max = 0;
        // Enumerate each point in increasing order.
        for (auto it = points.begin(); it != points.end(); ++it) {
            vector<int> start_point_heights = start_point_to_heights[*it];
            vector<int> end_point_heights = end_point_to_heights[*it];

            for (int i = 0; i < start_point_heights.size(); ++i) {
                ++height_to_count[start_point_heights[i]];
            }

            for (int i = 0; i < end_point_heights.size(); ++i) {
                --height_to_count[end_point_heights[i]];
                if (height_to_count[end_point_heights[i]] == 0) {
                    height_to_count.erase(end_point_heights[i]);
                }
            }

            if (height_to_count.empty() || curr_max != height_to_count.rbegin()->first) {
                if (curr_max > 0) {
                    res.emplace_back(move(vector<int>{curr_start, *it, curr_max}));
                }

                curr_start = *it;
                curr_max = height_to_count.empty() ? 0 : height_to_count.rbegin()->first;
            }
        }
        return res;
    }
};

<commit_msg>Update building-outline.cpp<commit_after>// Time:  O(nlogn)
// Space: O(n)

class Solution {
public:
    enum {start, end, height};
    /**
     * @param buildings: A list of lists of integers
     * @return: Find the outline of those buildings
     */
    vector<vector<int> > buildingOutline(vector<vector<int> > &buildings) {
        return ComputeSkylineInInterval(buildings, 0, buildings.size());
    }

    // Divide and Conquer.
    vector<vector<int>> ComputeSkylineInInterval(const vector<vector<int>>& buildings,
                                                 int left_endpoint, int right_endpoint) {
        if (right_endpoint - left_endpoint <= 1) {  // 0 or 1 skyline, just copy it.
            return {buildings.cbegin() + left_endpoint,
                buildings.cbegin() + right_endpoint};
        }
        int mid = left_endpoint + ((right_endpoint - left_endpoint) / 2);
        auto left_skyline = ComputeSkylineInInterval(buildings, left_endpoint, mid);
        auto right_skyline = ComputeSkylineInInterval(buildings, mid, right_endpoint);
        return MergeSkylines(left_skyline, right_skyline);
    }

    // Merge Sort
    vector<vector<int>> MergeSkylines(vector<vector<int>>& left_skyline, vector<vector<int>>& right_skyline) {
        int i = 0, j = 0;
        vector<vector<int>> merged;

        while (i < left_skyline.size() && j < right_skyline.size()) {
            if (left_skyline[i][end] < right_skyline[j][start]) {
                merged.emplace_back(left_skyline[i++]);
            } else if (right_skyline[j][end] < left_skyline[i][start]) {
                merged.emplace_back(right_skyline[j++]);
            } else if (left_skyline[i][start] <= right_skyline[j][start]) {
                MergeIntersectSkylines(merged, left_skyline[i], i,
                                       right_skyline[j], j);
            } else {  // left_skyline[i][start] > right_skyline[j][start].
                MergeIntersectSkylines(merged, right_skyline[j], j,
                                       left_skyline[i], i);
            }
        }

        // Insert the remaining skylines.
        merged.insert(merged.end(), left_skyline.begin() + i, left_skyline.end());
        merged.insert(merged.end(), right_skyline.begin() + j, right_skyline.end());
        return merged;
    }

    // a[start] <= b[start]
    void MergeIntersectSkylines(vector<vector<int>>& merged, vector<int>& a, int& a_idx,
                                vector<int>& b, int& b_idx) {
        if (a[end] <= b[end]) {
            if (a[height] > b[height]) {  // |aaa|
                if (b[end] != a[end]) {   // |abb|b
                    merged.emplace_back(a), ++a_idx;
                    b[start] = a[end];
                } else {        // aaa
                    ++b_idx;    // abb
                }
            } else if (a[height] == b[height]) { // abb
                b[start] = a[start], ++a_idx;    // abb
            } else {  // a[height] < b[height].
                if (a[start] != b[start]) {                                           //    bb
                    merged.emplace_back(vector<int>{a[start], b[start], a[height]});  // |a|bb
                }
                ++a_idx;
            }
        } else {  // a[end] > b[end].
            if (a[height] >= b[height]) {  // aaaa
                ++b_idx;                   // abba
            } else {
                //    |bb|
                // |a||bb|a
                if (a[start] != b[start]) {
                    merged.emplace_back(vector<int>{a[start], b[start], a[height]});
                }
                a[start] = b[end];
                merged.emplace_back(b), ++b_idx;
            }
        }
    }
};

// Time:  O(nlogn)
// Space: O(n)
class Solution2 {
public:
    /**
     * @param buildings: A list of lists of integers
     * @return: Find the outline of those buildings
     */
    vector<vector<int> > buildingOutline(vector<vector<int> > &buildings) {
        unordered_map<int, vector<int>> start_point_to_heights;
        unordered_map<int, vector<int>> end_point_to_heights;
        set<int> points;

        for (int i = 0; i < buildings.size(); ++i) {
            start_point_to_heights[buildings[i][0]].push_back(buildings[i][2]);
            end_point_to_heights[buildings[i][1]].push_back(buildings[i][2]);
            points.emplace(buildings[i][0]);
            points.emplace(buildings[i][1]);
        }

        vector<vector<int>> res;
        map<int, int> height_to_count;
        int curr_start = -1;
        int curr_max = 0;
        // Enumerate each point in increasing order.
        for (auto it = points.begin(); it != points.end(); ++it) {
            vector<int> start_point_heights = start_point_to_heights[*it];
            vector<int> end_point_heights = end_point_to_heights[*it];

            for (int i = 0; i < start_point_heights.size(); ++i) {
                ++height_to_count[start_point_heights[i]];
            }

            for (int i = 0; i < end_point_heights.size(); ++i) {
                --height_to_count[end_point_heights[i]];
                if (height_to_count[end_point_heights[i]] == 0) {
                    height_to_count.erase(end_point_heights[i]);
                }
            }

            if (height_to_count.empty() || curr_max != height_to_count.rbegin()->first) {
                if (curr_max > 0) {
                    res.emplace_back(move(vector<int>{curr_start, *it, curr_max}));
                }
                curr_start = *it;
                curr_max = height_to_count.empty() ? 0 : height_to_count.rbegin()->first;
            }
        }
        return res;
    }
};

<|endoftext|>