<commit_before>#ifndef QUORIDOR_WALK_MOVE_HPP_
#define QUORIDOR_WALK_MOVE_HPP_

#include "imove.hpp"
#include <boost/preprocessor.hpp>

#include <boost/preprocessor.hpp>

#define X_DEFINE_ENUM_WITH_STRING_CONVERSIONS_TOSTRING_CASE(r, data, elem)    \
    case elem : return BOOST_PP_STRINGIZE(elem);

#define DEFINE_ENUM_WITH_STRING_CONVERSIONS(name, enumerators)                \
    enum name {                                                               \
        BOOST_PP_SEQ_ENUM(enumerators)                                        \
    };                                                                        \
                                                                              \
    inline const char* ToString(name v)                                       \
    {                                                                         \
        switch (v)                                                            \
        {                                                                     \
            BOOST_PP_SEQ_FOR_EACH(                                            \
                X_DEFINE_ENUM_WITH_STRING_CONVERSIONS_TOSTRING_CASE,          \
                name,                                                         \
                enumerators                                                   \
            )                                                                 \
            default: return "[Unknown " BOOST_PP_STRINGIZE(name) "]";         \
        }                                                                     \
    }

namespace Quoridor {

class WalkMove : public IMove {
public:
    WalkMove();
    explicit WalkMove(int dir);
    virtual ~WalkMove();

    int dir() const { return dir_; }
    void set_dir(int dir) { dir_ = dir; }

public:
    DEFINE_ENUM_WITH_STRING_CONVERSIONS(Direction, (kForward)(kRight)(kBackward)(kLeft)(kEnd))

private:
    int dir_;
};

}  /* namespace Quoridor */

#endif  /* QUORIDOR_WALK_MOVE_HPP_ */
<commit_msg>Remove duplicated include.<commit_after>#ifndef QUORIDOR_WALK_MOVE_HPP_
#define QUORIDOR_WALK_MOVE_HPP_

#include "imove.hpp"
#include <boost/preprocessor.hpp>

#define X_DEFINE_ENUM_WITH_STRING_CONVERSIONS_TOSTRING_CASE(r, data, elem)    \
    case elem : return BOOST_PP_STRINGIZE(elem);

#define DEFINE_ENUM_WITH_STRING_CONVERSIONS(name, enumerators)                \
    enum name {                                                               \
        BOOST_PP_SEQ_ENUM(enumerators)                                        \
    };                                                                        \
                                                                              \
    inline const char* ToString(name v)                                       \
    {                                                                         \
        switch (v)                                                            \
        {                                                                     \
            BOOST_PP_SEQ_FOR_EACH(                                            \
                X_DEFINE_ENUM_WITH_STRING_CONVERSIONS_TOSTRING_CASE,          \
                name,                                                         \
                enumerators                                                   \
            )                                                                 \
            default: return "[Unknown " BOOST_PP_STRINGIZE(name) "]";         \
        }                                                                     \
    }

namespace Quoridor {

class WalkMove : public IMove {
public:
    WalkMove();
    explicit WalkMove(int dir);
    virtual ~WalkMove();

    int dir() const { return dir_; }
    void set_dir(int dir) { dir_ = dir; }

public:
    DEFINE_ENUM_WITH_STRING_CONVERSIONS(Direction, (kForward)(kRight)(kBackward)(kLeft)(kEnd))

private:
    int dir_;
};

}  /* namespace Quoridor */

#endif  /* QUORIDOR_WALK_MOVE_HPP_ */
<|endoftext|>


<commit_before>#include "x_client_name.hpp"

#include <xcb/xcb_ewmh.h>
#include <xcb/xcb_icccm.h>

x_client_name::x_client_name(x_connection & c,
                             x::xrm & xrm,
                             x_client & x_client)
  : m_c(c), m_xrm(xrm), m_x_client(x_client)
{
  m_c.attach(10, XCB_PROPERTY_NOTIFY, this);
  m_c.update_input(m_x_client.window(), XCB_EVENT_MASK_PROPERTY_CHANGE);

  m_xrm.attach(this);
  m_x_client.attach(this);

  load_config();

  update_wm_name();
  update_wm_class();
  update_net_wm_name();
}

x_client_name::~x_client_name(void)
{
  m_c.detach(XCB_PROPERTY_NOTIFY, this);
  m_xrm.detach(this);
  m_x_client.detach(this);
  xcb_free_pixmap(m_c(), m_title);
}

const std::string & x_client_name::net_wm_name(void) const
{
  return m_net_wm_name;
}

const std::string & x_client_name::wm_name(void) const
{
  return m_wm_name;
}

const std::string & x_client_name::wm_class_name(void) const
{
  return m_class_name;
}

const std::string & x_client_name::wm_instance_name(void) const
{
  return m_instance_name;
}

const xcb_pixmap_t &
x_client_name::title(void) const
{
  return m_title;
}

bool
x_client_name::handle(xcb_generic_event_t * ge)
{
  bool result = false;
  bool update_title = false;

  if (XCB_PROPERTY_NOTIFY == (ge->response_type & ~0x80)) {
    xcb_property_notify_event_t * e = (xcb_property_notify_event_t *)ge;

    if (e->window != m_x_client.window()) result = true;

    if (e->atom == m_a_wm_name) {
      update_title = true;
      update_wm_name();

    } else if (e->atom == m_a_wm_class) {
      update_title = true;
      update_wm_class();

    } else if (e->atom == m_a_net_wm_name) {
      update_title = true;
      update_net_wm_name();

    }

    result = true;
  }

  // TODO: cause clang to crash, FILE A BUG REPORT
#if defined  __GNUC__
  if (update_title) {
    observable::notify();
  }
#else
#error "Fix compilation with anything else but GNUC"
#endif

  return result;
}

void
x_client_name::notify(x::xrm *)
{
  load_config();
  // TODO: cause clang to crash, FILE A BUG REPORT
#if defined  __GNUC__
  observable::notify();
#else
#error "Fix compilation with anything else but GNUC"
#endif
}

void
x_client_name::notify(x_client *)
{
  // TODO: cause clang to crash, FILE A BUG REPORT
#if defined  __GNUC__
  observable::notify();
#else
#error "Fix compilation with anything else but GNUC"
#endif
}

// private

void
x_client_name::load_config(void)
{
  m_icon_size    = m_xrm["iconsize"].v.num;
  m_border_width = m_xrm["borderwidth"].v.num;
  m_pnamefont    = *m_xrm["titlefont"].v.str;
  m_titlefont    = *m_xrm["subtitlefont"].v.str;
  m_colorname    = *m_xrm["titlefgcolor"].v.str;

  m_title_bg_color =
    std::strtol(m_xrm["titlebgcolor"].v.str->substr(1,6).c_str(), NULL, 16);

  m_title_bg_color |= (int)(0xff * m_xrm["titlebgalpha"].v.dbl) << 24;
}

void
x_client_name::update_net_wm_name(void)
{
  m_net_wm_name.clear();

  xcb_generic_error_t * error;
  xcb_get_property_cookie_t c =
    xcb_ewmh_get_wm_name(m_c.ewmh(), m_x_client.window());
  xcb_get_property_reply_t * r = xcb_get_property_reply(m_c(), c, &error);

  if (error) {
    delete error;

  } else {
    xcb_ewmh_get_utf8_strings_reply_t net_wm_name;
    if (xcb_ewmh_get_wm_name_from_reply(m_c.ewmh(), &net_wm_name, r)) {
      m_net_wm_name = std::string(net_wm_name.strings, net_wm_name.strings_len);
      xcb_ewmh_get_utf8_strings_reply_wipe(&net_wm_name);
      r = NULL;
    }
  }

  if (r) delete r;
}

void
x_client_name::update_wm_name(void)
{
  m_wm_name.clear();

  xcb_generic_error_t * error;
  xcb_icccm_get_text_property_reply_t wm_name;
  xcb_get_property_cookie_t c =
    xcb_icccm_get_wm_name(m_c(), m_x_client.window());
  xcb_icccm_get_wm_name_reply(m_c(), c, &wm_name, &error);

  // TODO: cause clang to crash, FILE A BUG REPORT
#if defined  __GNUC__
  if (error) {
    delete error;

  } else {
    m_wm_name = std::string(wm_name.name, wm_name.name_len);
    xcb_icccm_get_text_property_reply_wipe(&wm_name);
  }

#else
#error "Fix compilation with anything else but GNUC"
#endif
}

void
x_client_name::update_wm_class(void)
{
  m_class_name.clear();
  m_instance_name.clear();

  xcb_generic_error_t * error;
  xcb_get_property_cookie_t c =
    xcb_icccm_get_wm_class(m_c(), m_x_client.window());
  xcb_get_property_reply_t * r = xcb_get_property_reply(m_c(), c, &error);

  if (error) {
    delete error;

  } else {
    xcb_icccm_get_wm_class_reply_t wm_class;
    if (xcb_icccm_get_wm_class_from_reply(&wm_class, r)) {
      m_class_name = wm_class.class_name;
      m_instance_name = wm_class.instance_name;
      xcb_icccm_get_wm_class_reply_wipe(&wm_class);
      r = NULL;
    }
  }

  if (r) delete r;
}

void
x_client_name::make_title(void)
{
  xcb_free_pixmap(m_c(), m_title);

  m_title = xcb_generate_id(m_c());
  xcb_create_pixmap(m_c(), 32, m_title, m_c.root_window(),
                    m_title_width, m_title_height);

  xcb_gcontext_t gc = xcb_generate_id(m_c());
  xcb_create_gc(m_c(), gc, m_title, XCB_GC_FOREGROUND, &m_title_bg_color );
  xcb_rectangle_t r = { 0, 0, (uint16_t)m_title_width, (uint16_t)m_title_height };
  xcb_poly_fill_rectangle(m_c(), m_title, gc, 1, &r);
  xcb_free_gc(m_c(), gc);

  m_x_xft = std::shared_ptr<x::xft>(new x::xft(m_c.dpy(), m_title, 32));

  std::string pname = m_class_name;
  std::string title = m_net_wm_name.empty() ? m_wm_name : m_net_wm_name;

  std::string lower = "abcdefghijklmnopqrstuvwxy";
  std::string upper = "ABCDEFGHIJKLMNOPQRSTUVWXY";

  XGlyphInfo text_extents = m_x_xft->text_extents_utf8(m_pnamefont, lower + upper);

  int x_off = m_icon_size + 3 * m_border_width;
  int y_off = m_border_width;

  y_off += text_extents.height;
  m_x_xft->draw_string_utf8(pname, x_off, y_off, m_pnamefont, m_colorname);

  y_off += text_extents.height;
  m_x_xft->draw_string_utf8(title, x_off, y_off, m_titlefont, m_colorname);
}
<commit_msg>Add a bit more spacing between logo & title<commit_after>#include "x_client_name.hpp"

#include <xcb/xcb_ewmh.h>
#include <xcb/xcb_icccm.h>

x_client_name::x_client_name(x_connection & c,
                             x::xrm & xrm,
                             x_client & x_client)
  : m_c(c), m_xrm(xrm), m_x_client(x_client)
{
  m_c.attach(10, XCB_PROPERTY_NOTIFY, this);
  m_c.update_input(m_x_client.window(), XCB_EVENT_MASK_PROPERTY_CHANGE);

  m_xrm.attach(this);
  m_x_client.attach(this);

  load_config();

  update_wm_name();
  update_wm_class();
  update_net_wm_name();
}

x_client_name::~x_client_name(void)
{
  m_c.detach(XCB_PROPERTY_NOTIFY, this);
  m_xrm.detach(this);
  m_x_client.detach(this);
  xcb_free_pixmap(m_c(), m_title);
}

const std::string & x_client_name::net_wm_name(void) const
{
  return m_net_wm_name;
}

const std::string & x_client_name::wm_name(void) const
{
  return m_wm_name;
}

const std::string & x_client_name::wm_class_name(void) const
{
  return m_class_name;
}

const std::string & x_client_name::wm_instance_name(void) const
{
  return m_instance_name;
}

const xcb_pixmap_t &
x_client_name::title(void) const
{
  return m_title;
}

bool
x_client_name::handle(xcb_generic_event_t * ge)
{
  bool result = false;
  bool update_title = false;

  if (XCB_PROPERTY_NOTIFY == (ge->response_type & ~0x80)) {
    xcb_property_notify_event_t * e = (xcb_property_notify_event_t *)ge;

    if (e->window != m_x_client.window()) result = true;

    if (e->atom == m_a_wm_name) {
      update_title = true;
      update_wm_name();

    } else if (e->atom == m_a_wm_class) {
      update_title = true;
      update_wm_class();

    } else if (e->atom == m_a_net_wm_name) {
      update_title = true;
      update_net_wm_name();

    }

    result = true;
  }

  // TODO: cause clang to crash, FILE A BUG REPORT
#if defined  __GNUC__
  if (update_title) {
    observable::notify();
  }
#else
#error "Fix compilation with anything else but GNUC"
#endif

  return result;
}

void
x_client_name::notify(x::xrm *)
{
  load_config();
  // TODO: cause clang to crash, FILE A BUG REPORT
#if defined  __GNUC__
  observable::notify();
#else
#error "Fix compilation with anything else but GNUC"
#endif
}

void
x_client_name::notify(x_client *)
{
  // TODO: cause clang to crash, FILE A BUG REPORT
#if defined  __GNUC__
  observable::notify();
#else
#error "Fix compilation with anything else but GNUC"
#endif
}

// private

void
x_client_name::load_config(void)
{
  m_icon_size    = m_xrm["iconsize"].v.num;
  m_border_width = m_xrm["borderwidth"].v.num;
  m_pnamefont    = *m_xrm["titlefont"].v.str;
  m_titlefont    = *m_xrm["subtitlefont"].v.str;
  m_colorname    = *m_xrm["titlefgcolor"].v.str;

  m_title_bg_color =
    std::strtol(m_xrm["titlebgcolor"].v.str->substr(1,6).c_str(), NULL, 16);

  m_title_bg_color |= (int)(0xff * m_xrm["titlebgalpha"].v.dbl) << 24;
}

void
x_client_name::update_net_wm_name(void)
{
  m_net_wm_name.clear();

  xcb_generic_error_t * error;
  xcb_get_property_cookie_t c =
    xcb_ewmh_get_wm_name(m_c.ewmh(), m_x_client.window());
  xcb_get_property_reply_t * r = xcb_get_property_reply(m_c(), c, &error);

  if (error) {
    delete error;

  } else {
    xcb_ewmh_get_utf8_strings_reply_t net_wm_name;
    if (xcb_ewmh_get_wm_name_from_reply(m_c.ewmh(), &net_wm_name, r)) {
      m_net_wm_name = std::string(net_wm_name.strings, net_wm_name.strings_len);
      xcb_ewmh_get_utf8_strings_reply_wipe(&net_wm_name);
      r = NULL;
    }
  }

  if (r) delete r;
}

void
x_client_name::update_wm_name(void)
{
  m_wm_name.clear();

  xcb_generic_error_t * error;
  xcb_icccm_get_text_property_reply_t wm_name;
  xcb_get_property_cookie_t c =
    xcb_icccm_get_wm_name(m_c(), m_x_client.window());
  xcb_icccm_get_wm_name_reply(m_c(), c, &wm_name, &error);

  // TODO: cause clang to crash, FILE A BUG REPORT
#if defined  __GNUC__
  if (error) {
    delete error;

  } else {
    m_wm_name = std::string(wm_name.name, wm_name.name_len);
    xcb_icccm_get_text_property_reply_wipe(&wm_name);
  }

#else
#error "Fix compilation with anything else but GNUC"
#endif
}

void
x_client_name::update_wm_class(void)
{
  m_class_name.clear();
  m_instance_name.clear();

  xcb_generic_error_t * error;
  xcb_get_property_cookie_t c =
    xcb_icccm_get_wm_class(m_c(), m_x_client.window());
  xcb_get_property_reply_t * r = xcb_get_property_reply(m_c(), c, &error);

  if (error) {
    delete error;

  } else {
    xcb_icccm_get_wm_class_reply_t wm_class;
    if (xcb_icccm_get_wm_class_from_reply(&wm_class, r)) {
      m_class_name = wm_class.class_name;
      m_instance_name = wm_class.instance_name;
      xcb_icccm_get_wm_class_reply_wipe(&wm_class);
      r = NULL;
    }
  }

  if (r) delete r;
}

void
x_client_name::make_title(void)
{
  xcb_free_pixmap(m_c(), m_title);

  m_title = xcb_generate_id(m_c());
  xcb_create_pixmap(m_c(), 32, m_title, m_c.root_window(),
                    m_title_width, m_title_height);

  xcb_gcontext_t gc = xcb_generate_id(m_c());
  xcb_create_gc(m_c(), gc, m_title, XCB_GC_FOREGROUND, &m_title_bg_color );
  xcb_rectangle_t r = { 0, 0, (uint16_t)m_title_width, (uint16_t)m_title_height };
  xcb_poly_fill_rectangle(m_c(), m_title, gc, 1, &r);
  xcb_free_gc(m_c(), gc);

  m_x_xft = std::shared_ptr<x::xft>(new x::xft(m_c.dpy(), m_title, 32));

  std::string pname = m_class_name;
  std::string title = m_net_wm_name.empty() ? m_wm_name : m_net_wm_name;

  std::string lower = "abcdefghijklmnopqrstuvwxy";
  std::string upper = "ABCDEFGHIJKLMNOPQRSTUVWXY";

  XGlyphInfo text_extents = m_x_xft->text_extents_utf8(m_pnamefont, lower + upper);

  int x_off = m_icon_size + 4 * m_border_width;
  int y_off = m_border_width;

  y_off += text_extents.height;
  m_x_xft->draw_string_utf8(pname, x_off, y_off, m_pnamefont, m_colorname);

  y_off += text_extents.height;
  m_x_xft->draw_string_utf8(title, x_off, y_off, m_titlefont, m_colorname);
}
<|endoftext|>


<commit_before>/**
 ******************************************************************************
 * Xenia : Xbox 360 Emulator Research Project                                 *
 ******************************************************************************
 * Copyright 2013 Ben Vanik. All rights reserved.                             *
 * Released under the BSD license - see LICENSE in the root for more details. *
 ******************************************************************************
 */

#include "xenia/emulator.h"

#include <gflags/gflags.h>

#include "third_party/elemental-forms/src/el/elements.h"
#include "xenia/apu/audio_system.h"
#include "xenia/base/assert.h"
#include "xenia/base/clock.h"
#include "xenia/base/debugging.h"
#include "xenia/base/exception_handler.h"
#include "xenia/base/logging.h"
#include "xenia/base/string.h"
#include "xenia/cpu/backend/code_cache.h"
#include "xenia/gpu/graphics_system.h"
#include "xenia/hid/input_system.h"
#include "xenia/kernel/kernel_state.h"
#include "xenia/kernel/xam/xam_module.h"
#include "xenia/kernel/xboxkrnl/xboxkrnl_module.h"
#include "xenia/memory.h"
#include "xenia/vfs/devices/disc_image_device.h"
#include "xenia/vfs/devices/host_path_device.h"
#include "xenia/vfs/devices/stfs_container_device.h"
#include "xenia/vfs/virtual_file_system.h"

DEFINE_double(time_scalar, 1.0,
              "Scalar used to speed or slow time (1x, 2x, 1/2x, etc).");

namespace xe {

Emulator::Emulator(const std::wstring& command_line)
    : command_line_(command_line) {}

Emulator::~Emulator() {
  // Note that we delete things in the reverse order they were initialized.

  if (debugger_) {
    // Kill the debugger first, so that we don't have it messing with things.
    debugger_->StopSession();
  }

  // Give the systems time to shutdown before we delete them.
  graphics_system_->Shutdown();
  audio_system_->Shutdown();

  input_system_.reset();
  graphics_system_.reset();
  audio_system_.reset();

  kernel_state_.reset();
  file_system_.reset();

  processor_.reset();

  debugger_.reset();

  export_resolver_.reset();

  ExceptionHandler::Uninstall(Emulator::ExceptionCallbackThunk, this);
}

X_STATUS Emulator::Setup(ui::Window* display_window) {
  X_STATUS result = X_STATUS_UNSUCCESSFUL;

  display_window_ = display_window;

  // Initialize clock.
  // 360 uses a 50MHz clock.
  Clock::set_guest_tick_frequency(50000000);
  // We could reset this with save state data/constant value to help replays.
  Clock::set_guest_system_time_base(Clock::QueryHostSystemTime());
  // This can be adjusted dynamically, as well.
  Clock::set_guest_time_scalar(FLAGS_time_scalar);

  // Before we can set thread affinity we must enable the process to use all
  // logical processors.
  xe::threading::EnableAffinityConfiguration();

  // Create memory system first, as it is required for other systems.
  memory_ = std::make_unique<Memory>();
  result = memory_->Initialize();
  if (result) {
    return result;
  }

  // Shared export resolver used to attach and query for HLE exports.
  export_resolver_ = std::make_unique<xe::cpu::ExportResolver>();

  if (FLAGS_debug) {
    // Debugger first, as other parts hook into it.
    debugger_.reset(new debug::Debugger(this));

    // Create debugger first. Other types hook up to it.
    debugger_->StartSession();
  }

  // Initialize the CPU.
  processor_ = std::make_unique<xe::cpu::Processor>(
      memory_.get(), export_resolver_.get(), debugger_.get());

  // Initialize the APU.
  audio_system_ = xe::apu::AudioSystem::Create(processor_.get());
  if (!audio_system_) {
    return X_STATUS_NOT_IMPLEMENTED;
  }

  // Initialize the GPU.
  graphics_system_ = xe::gpu::GraphicsSystem::Create(this);
  if (!graphics_system_) {
    return X_STATUS_NOT_IMPLEMENTED;
  }
  display_window_->loop()->PostSynchronous([this]() {
    display_window_->set_context(
        graphics_system_->CreateContext(display_window_));
  });

  // Initialize the HID.
  input_system_ = xe::hid::InputSystem::Create(this);
  if (!input_system_) {
    return X_STATUS_NOT_IMPLEMENTED;
  }

  result = input_system_->Setup();
  if (result) {
    return result;
  }

  // Bring up the virtual filesystem used by the kernel.
  file_system_ = std::make_unique<xe::vfs::VirtualFileSystem>();

  // Shared kernel state.
  kernel_state_ = std::make_unique<xe::kernel::KernelState>(this);

  // Setup the core components.
  if (!processor_->Setup()) {
    return result;
  }
  result = graphics_system_->Setup(processor_.get(), display_window_->loop(),
                                   display_window_);
  if (result) {
    return result;
  }

  result = audio_system_->Setup(kernel_state_.get());
  if (result) {
    return result;
  }

  // HLE kernel modules.
  kernel_state_->LoadKernelModule<kernel::xboxkrnl::XboxkrnlModule>();
  kernel_state_->LoadKernelModule<kernel::xam::XamModule>();

  // Initialize emulator fallback exception handling last.
  ExceptionHandler::Install(Emulator::ExceptionCallbackThunk, this);

  // Finish initializing the display.
  display_window_->loop()->PostSynchronous([this]() {
    xe::ui::GraphicsContextLock context_lock(display_window_->context());
    auto profiler_display = display_window_->context()->CreateProfilerDisplay();
    Profiler::set_display(std::move(profiler_display));
  });

  return result;
}

X_STATUS Emulator::LaunchPath(std::wstring path) {
  // Launch based on file type.
  // This is a silly guess based on file extension.
  auto last_slash = path.find_last_of(xe::kPathSeparator);
  auto last_dot = path.find_last_of('.');
  if (last_dot < last_slash) {
    last_dot = std::wstring::npos;
  }
  if (last_dot == std::wstring::npos) {
    // Likely an STFS container.
    return LaunchStfsContainer(path);
  } else if (path.substr(last_dot) == L".xex" ||
             path.substr(last_dot) == L".elf") {
    // Treat as a naked xex file.
    return LaunchXexFile(path);
  } else {
    // Assume a disc image.
    return LaunchDiscImage(path);
  }
}

X_STATUS Emulator::LaunchXexFile(std::wstring path) {
  // We create a virtual filesystem pointing to its directory and symlink
  // that to the game filesystem.
  // e.g., /my/files/foo.xex will get a local fs at:
  // \\Device\\Harddisk0\\Partition1
  // and then get that symlinked to game:\, so
  // -> game:\foo.xex

  auto mount_path = "\\Device\\Harddisk0\\Partition0";

  // Register the local directory in the virtual filesystem.
  auto parent_path = xe::find_base_path(path);
  auto device =
      std::make_unique<vfs::HostPathDevice>(mount_path, parent_path, true);
  if (!device->Initialize()) {
    XELOGE("Unable to scan host path");
    return X_STATUS_NO_SUCH_FILE;
  }
  if (!file_system_->RegisterDevice(std::move(device))) {
    XELOGE("Unable to register host path");
    return X_STATUS_NO_SUCH_FILE;
  }

  // Create symlinks to the device.
  file_system_->RegisterSymbolicLink("game:", mount_path);
  file_system_->RegisterSymbolicLink("d:", mount_path);

  // Get just the filename (foo.xex).
  auto file_name = xe::find_name_from_path(path);

  // Launch the game.
  std::string fs_path = "game:\\" + xe::to_string(file_name);
  return CompleteLaunch(path, fs_path);
}

X_STATUS Emulator::LaunchDiscImage(std::wstring path) {
  auto mount_path = "\\Device\\Cdrom0";

  // Register the disc image in the virtual filesystem.
  auto device = std::make_unique<vfs::DiscImageDevice>(mount_path, path);
  if (!device->Initialize()) {
    xe::FatalError("Unable to mount disc image; file not found or corrupt.");
    return X_STATUS_NO_SUCH_FILE;
  }
  if (!file_system_->RegisterDevice(std::move(device))) {
    xe::FatalError("Unable to register disc image.");
    return X_STATUS_NO_SUCH_FILE;
  }

  // Create symlinks to the device.
  file_system_->RegisterSymbolicLink("game:", mount_path);
  file_system_->RegisterSymbolicLink("d:", mount_path);

  // Launch the game.
  return CompleteLaunch(path, "game:\\default.xex");
}

X_STATUS Emulator::LaunchStfsContainer(std::wstring path) {
  auto mount_path = "\\Device\\Cdrom0";

  // Register the container in the virtual filesystem.
  auto device = std::make_unique<vfs::StfsContainerDevice>(mount_path, path);
  if (!device->Initialize()) {
    xe::FatalError(
        "Unable to mount STFS container; file not found or corrupt.");
    return X_STATUS_NO_SUCH_FILE;
  }
  if (!file_system_->RegisterDevice(std::move(device))) {
    xe::FatalError("Unable to register STFS container.");
    return X_STATUS_NO_SUCH_FILE;
  }

  file_system_->RegisterSymbolicLink("game:", mount_path);
  file_system_->RegisterSymbolicLink("d:", mount_path);

  // Launch the game.
  return CompleteLaunch(path, "game:\\default.xex");
}

bool Emulator::ExceptionCallbackThunk(Exception* ex, void* data) {
  return reinterpret_cast<Emulator*>(data)->ExceptionCallback(ex);
}

bool Emulator::ExceptionCallback(Exception* ex) {
  // Check to see if the exception occurred in guest code.
  auto code_cache = processor()->backend()->code_cache();
  auto code_base = code_cache->base_address();
  auto code_end = code_base + code_cache->total_size();

  if (!debugger() ||
      !debugger()->is_attached() && debugging::IsDebuggerAttached()) {
    // If Xenia's debugger isn't attached but another one is, pass it to that
    // debugger.
    return false;
  } else if (debugger() && debugger()->is_attached()) {
    // Let the debugger handle this exception. It may decide to continue past it
    // (if it was a stepping breakpoint, etc).
    return debugger()->OnUnhandledException(ex);
  }

  if (!(ex->pc() >= code_base && ex->pc() < code_end)) {
    // Didn't occur in guest code. Let it pass.
    return false;
  }

  auto global_lock = global_critical_region::AcquireDirect();

  // Within range. Pause the emulator and eat the exception.
  auto threads =
      kernel_state()->object_table()->GetObjectsByType<kernel::XThread>(
          kernel::XObject::kTypeThread);
  auto current_thread = kernel::XThread::GetCurrentThread();
  for (auto thread : threads) {
    if (!thread->can_debugger_suspend()) {
      // Don't pause host threads.
      continue;
    }
    if (current_thread == thread.get()) {
      continue;
    }
    thread->Suspend(nullptr);
  }

  // Display a dialog telling the user the guest has crashed.
  display_window()->loop()->PostSynchronous([&]() {
    auto message_form = new el::MessageForm(display_window()->root_element(),
                                            TBIDC("crash_form"));
    message_form->Show("Uh-oh!",
                       "The guest has crashed.\n\n"
                       "Xenia has now paused itself.");
  });

  // Now suspend ourself (we should be a guest thread).
  assert_true(current_thread->can_debugger_suspend());
  current_thread->Suspend(nullptr);

  // We should not arrive here!
  assert_always();
  return false;
}

X_STATUS Emulator::CompleteLaunch(const std::wstring& path,
                                  const std::string& module_path) {
  // Allow xam to request module loads.
  auto xam = kernel_state()->GetKernelModule<kernel::xam::XamModule>("xam.xex");
  auto xboxkrnl =
      kernel_state()->GetKernelModule<kernel::xboxkrnl::XboxkrnlModule>(
          "xboxkrnl.exe");

  int result = 0;
  auto next_module = module_path;
  while (next_module != "") {
    XELOGI("Launching module %s", next_module.c_str());
    result = xboxkrnl->LaunchModule(next_module.c_str());

    // Check xam and see if they want us to load another module.
    auto& loader_data = xam->loader_data();
    next_module = loader_data.launch_path;

    // And blank out the launch path to avoid an infinite loop.
    loader_data.launch_path = "";
  }

  if (result == 0) {
    return X_STATUS_SUCCESS;
  } else {
    return X_STATUS_UNSUCCESSFUL;
  }
}

}  // namespace xe
<commit_msg>Fix logical-op parenthesis error from clang.<commit_after>/**
 ******************************************************************************
 * Xenia : Xbox 360 Emulator Research Project                                 *
 ******************************************************************************
 * Copyright 2013 Ben Vanik. All rights reserved.                             *
 * Released under the BSD license - see LICENSE in the root for more details. *
 ******************************************************************************
 */

#include "xenia/emulator.h"

#include <gflags/gflags.h>

#include "third_party/elemental-forms/src/el/elements.h"
#include "xenia/apu/audio_system.h"
#include "xenia/base/assert.h"
#include "xenia/base/clock.h"
#include "xenia/base/debugging.h"
#include "xenia/base/exception_handler.h"
#include "xenia/base/logging.h"
#include "xenia/base/string.h"
#include "xenia/cpu/backend/code_cache.h"
#include "xenia/gpu/graphics_system.h"
#include "xenia/hid/input_system.h"
#include "xenia/kernel/kernel_state.h"
#include "xenia/kernel/xam/xam_module.h"
#include "xenia/kernel/xboxkrnl/xboxkrnl_module.h"
#include "xenia/memory.h"
#include "xenia/vfs/devices/disc_image_device.h"
#include "xenia/vfs/devices/host_path_device.h"
#include "xenia/vfs/devices/stfs_container_device.h"
#include "xenia/vfs/virtual_file_system.h"

DEFINE_double(time_scalar, 1.0,
              "Scalar used to speed or slow time (1x, 2x, 1/2x, etc).");

namespace xe {

Emulator::Emulator(const std::wstring& command_line)
    : command_line_(command_line) {}

Emulator::~Emulator() {
  // Note that we delete things in the reverse order they were initialized.

  if (debugger_) {
    // Kill the debugger first, so that we don't have it messing with things.
    debugger_->StopSession();
  }

  // Give the systems time to shutdown before we delete them.
  graphics_system_->Shutdown();
  audio_system_->Shutdown();

  input_system_.reset();
  graphics_system_.reset();
  audio_system_.reset();

  kernel_state_.reset();
  file_system_.reset();

  processor_.reset();

  debugger_.reset();

  export_resolver_.reset();

  ExceptionHandler::Uninstall(Emulator::ExceptionCallbackThunk, this);
}

X_STATUS Emulator::Setup(ui::Window* display_window) {
  X_STATUS result = X_STATUS_UNSUCCESSFUL;

  display_window_ = display_window;

  // Initialize clock.
  // 360 uses a 50MHz clock.
  Clock::set_guest_tick_frequency(50000000);
  // We could reset this with save state data/constant value to help replays.
  Clock::set_guest_system_time_base(Clock::QueryHostSystemTime());
  // This can be adjusted dynamically, as well.
  Clock::set_guest_time_scalar(FLAGS_time_scalar);

  // Before we can set thread affinity we must enable the process to use all
  // logical processors.
  xe::threading::EnableAffinityConfiguration();

  // Create memory system first, as it is required for other systems.
  memory_ = std::make_unique<Memory>();
  result = memory_->Initialize();
  if (result) {
    return result;
  }

  // Shared export resolver used to attach and query for HLE exports.
  export_resolver_ = std::make_unique<xe::cpu::ExportResolver>();

  if (FLAGS_debug) {
    // Debugger first, as other parts hook into it.
    debugger_.reset(new debug::Debugger(this));

    // Create debugger first. Other types hook up to it.
    debugger_->StartSession();
  }

  // Initialize the CPU.
  processor_ = std::make_unique<xe::cpu::Processor>(
      memory_.get(), export_resolver_.get(), debugger_.get());

  // Initialize the APU.
  audio_system_ = xe::apu::AudioSystem::Create(processor_.get());
  if (!audio_system_) {
    return X_STATUS_NOT_IMPLEMENTED;
  }

  // Initialize the GPU.
  graphics_system_ = xe::gpu::GraphicsSystem::Create(this);
  if (!graphics_system_) {
    return X_STATUS_NOT_IMPLEMENTED;
  }
  display_window_->loop()->PostSynchronous([this]() {
    display_window_->set_context(
        graphics_system_->CreateContext(display_window_));
  });

  // Initialize the HID.
  input_system_ = xe::hid::InputSystem::Create(this);
  if (!input_system_) {
    return X_STATUS_NOT_IMPLEMENTED;
  }

  result = input_system_->Setup();
  if (result) {
    return result;
  }

  // Bring up the virtual filesystem used by the kernel.
  file_system_ = std::make_unique<xe::vfs::VirtualFileSystem>();

  // Shared kernel state.
  kernel_state_ = std::make_unique<xe::kernel::KernelState>(this);

  // Setup the core components.
  if (!processor_->Setup()) {
    return result;
  }
  result = graphics_system_->Setup(processor_.get(), display_window_->loop(),
                                   display_window_);
  if (result) {
    return result;
  }

  result = audio_system_->Setup(kernel_state_.get());
  if (result) {
    return result;
  }

  // HLE kernel modules.
  kernel_state_->LoadKernelModule<kernel::xboxkrnl::XboxkrnlModule>();
  kernel_state_->LoadKernelModule<kernel::xam::XamModule>();

  // Initialize emulator fallback exception handling last.
  ExceptionHandler::Install(Emulator::ExceptionCallbackThunk, this);

  // Finish initializing the display.
  display_window_->loop()->PostSynchronous([this]() {
    xe::ui::GraphicsContextLock context_lock(display_window_->context());
    auto profiler_display = display_window_->context()->CreateProfilerDisplay();
    Profiler::set_display(std::move(profiler_display));
  });

  return result;
}

X_STATUS Emulator::LaunchPath(std::wstring path) {
  // Launch based on file type.
  // This is a silly guess based on file extension.
  auto last_slash = path.find_last_of(xe::kPathSeparator);
  auto last_dot = path.find_last_of('.');
  if (last_dot < last_slash) {
    last_dot = std::wstring::npos;
  }
  if (last_dot == std::wstring::npos) {
    // Likely an STFS container.
    return LaunchStfsContainer(path);
  } else if (path.substr(last_dot) == L".xex" ||
             path.substr(last_dot) == L".elf") {
    // Treat as a naked xex file.
    return LaunchXexFile(path);
  } else {
    // Assume a disc image.
    return LaunchDiscImage(path);
  }
}

X_STATUS Emulator::LaunchXexFile(std::wstring path) {
  // We create a virtual filesystem pointing to its directory and symlink
  // that to the game filesystem.
  // e.g., /my/files/foo.xex will get a local fs at:
  // \\Device\\Harddisk0\\Partition1
  // and then get that symlinked to game:\, so
  // -> game:\foo.xex

  auto mount_path = "\\Device\\Harddisk0\\Partition0";

  // Register the local directory in the virtual filesystem.
  auto parent_path = xe::find_base_path(path);
  auto device =
      std::make_unique<vfs::HostPathDevice>(mount_path, parent_path, true);
  if (!device->Initialize()) {
    XELOGE("Unable to scan host path");
    return X_STATUS_NO_SUCH_FILE;
  }
  if (!file_system_->RegisterDevice(std::move(device))) {
    XELOGE("Unable to register host path");
    return X_STATUS_NO_SUCH_FILE;
  }

  // Create symlinks to the device.
  file_system_->RegisterSymbolicLink("game:", mount_path);
  file_system_->RegisterSymbolicLink("d:", mount_path);

  // Get just the filename (foo.xex).
  auto file_name = xe::find_name_from_path(path);

  // Launch the game.
  std::string fs_path = "game:\\" + xe::to_string(file_name);
  return CompleteLaunch(path, fs_path);
}

X_STATUS Emulator::LaunchDiscImage(std::wstring path) {
  auto mount_path = "\\Device\\Cdrom0";

  // Register the disc image in the virtual filesystem.
  auto device = std::make_unique<vfs::DiscImageDevice>(mount_path, path);
  if (!device->Initialize()) {
    xe::FatalError("Unable to mount disc image; file not found or corrupt.");
    return X_STATUS_NO_SUCH_FILE;
  }
  if (!file_system_->RegisterDevice(std::move(device))) {
    xe::FatalError("Unable to register disc image.");
    return X_STATUS_NO_SUCH_FILE;
  }

  // Create symlinks to the device.
  file_system_->RegisterSymbolicLink("game:", mount_path);
  file_system_->RegisterSymbolicLink("d:", mount_path);

  // Launch the game.
  return CompleteLaunch(path, "game:\\default.xex");
}

X_STATUS Emulator::LaunchStfsContainer(std::wstring path) {
  auto mount_path = "\\Device\\Cdrom0";

  // Register the container in the virtual filesystem.
  auto device = std::make_unique<vfs::StfsContainerDevice>(mount_path, path);
  if (!device->Initialize()) {
    xe::FatalError(
        "Unable to mount STFS container; file not found or corrupt.");
    return X_STATUS_NO_SUCH_FILE;
  }
  if (!file_system_->RegisterDevice(std::move(device))) {
    xe::FatalError("Unable to register STFS container.");
    return X_STATUS_NO_SUCH_FILE;
  }

  file_system_->RegisterSymbolicLink("game:", mount_path);
  file_system_->RegisterSymbolicLink("d:", mount_path);

  // Launch the game.
  return CompleteLaunch(path, "game:\\default.xex");
}

bool Emulator::ExceptionCallbackThunk(Exception* ex, void* data) {
  return reinterpret_cast<Emulator*>(data)->ExceptionCallback(ex);
}

bool Emulator::ExceptionCallback(Exception* ex) {
  // Check to see if the exception occurred in guest code.
  auto code_cache = processor()->backend()->code_cache();
  auto code_base = code_cache->base_address();
  auto code_end = code_base + code_cache->total_size();

  if (!debugger() ||
      (!debugger()->is_attached() && debugging::IsDebuggerAttached())) {
    // If Xenia's debugger isn't attached but another one is, pass it to that
    // debugger.
    return false;
  } else if (debugger() && debugger()->is_attached()) {
    // Let the debugger handle this exception. It may decide to continue past it
    // (if it was a stepping breakpoint, etc).
    return debugger()->OnUnhandledException(ex);
  }

  if (!(ex->pc() >= code_base && ex->pc() < code_end)) {
    // Didn't occur in guest code. Let it pass.
    return false;
  }

  auto global_lock = global_critical_region::AcquireDirect();

  // Within range. Pause the emulator and eat the exception.
  auto threads =
      kernel_state()->object_table()->GetObjectsByType<kernel::XThread>(
          kernel::XObject::kTypeThread);
  auto current_thread = kernel::XThread::GetCurrentThread();
  for (auto thread : threads) {
    if (!thread->can_debugger_suspend()) {
      // Don't pause host threads.
      continue;
    }
    if (current_thread == thread.get()) {
      continue;
    }
    thread->Suspend(nullptr);
  }

  // Display a dialog telling the user the guest has crashed.
  display_window()->loop()->PostSynchronous([&]() {
    auto message_form = new el::MessageForm(display_window()->root_element(),
                                            TBIDC("crash_form"));
    message_form->Show("Uh-oh!",
                       "The guest has crashed.\n\n"
                       "Xenia has now paused itself.");
  });

  // Now suspend ourself (we should be a guest thread).
  assert_true(current_thread->can_debugger_suspend());
  current_thread->Suspend(nullptr);

  // We should not arrive here!
  assert_always();
  return false;
}

X_STATUS Emulator::CompleteLaunch(const std::wstring& path,
                                  const std::string& module_path) {
  // Allow xam to request module loads.
  auto xam = kernel_state()->GetKernelModule<kernel::xam::XamModule>("xam.xex");
  auto xboxkrnl =
      kernel_state()->GetKernelModule<kernel::xboxkrnl::XboxkrnlModule>(
          "xboxkrnl.exe");

  int result = 0;
  auto next_module = module_path;
  while (next_module != "") {
    XELOGI("Launching module %s", next_module.c_str());
    result = xboxkrnl->LaunchModule(next_module.c_str());

    // Check xam and see if they want us to load another module.
    auto& loader_data = xam->loader_data();
    next_module = loader_data.launch_path;

    // And blank out the launch path to avoid an infinite loop.
    loader_data.launch_path = "";
  }

  if (result == 0) {
    return X_STATUS_SUCCESS;
  } else {
    return X_STATUS_UNSUCCESSFUL;
  }
}

}  // namespace xe
<|endoftext|>


<commit_before>/**
 * Copyright (c) 2015 - The CM Authors <legal@clickmatcher.com>
 *   All Rights Reserved.
 *
 * This file is CONFIDENTIAL -- Distribution or duplication of this material or
 * the information contained herein is strictly forbidden unless prior written
 * permission is obtained.
 */
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>
#include "stx/io/filerepository.h"
#include "stx/io/fileutil.h"
#include "stx/application.h"
#include "stx/logging.h"
#include "stx/random.h"
#include "stx/thread/eventloop.h"
#include "stx/thread/threadpool.h"
#include "stx/thread/FixedSizeThreadPool.h"
#include "stx/wallclock.h"
#include "stx/VFS.h"
#include "stx/cli/flagparser.h"
#include "stx/json/json.h"
#include "stx/json/jsonrpc.h"
#include "stx/http/httprouter.h"
#include "stx/http/httpserver.h"
#include "stx/http/httpconnectionpool.h"
#include "stx/http/VFSFileServlet.h"
#include "stx/cli/CLI.h"
#include "stx/cli/flagparser.h"
#include "zbase/dproc/LocalScheduler.h"
#include "zbase/dproc/DispatchService.h"
#include "zbase/ConfigDirectory.h"
#include "sstable/sstablereader.h"
#include "zbase/JoinedSession.pb.h"
#include "zbase/core/TimeWindowPartitioner.h"
#include "zbase/core/TSDBClient.h"
#include "csql/qtree/SequentialScanNode.h"
#include "csql/qtree/ColumnReferenceNode.h"
#include "csql/qtree/CallExpressionNode.h"
#include "csql/qtree/GroupByNode.h"
#include "csql/qtree/UnionNode.h"
#include "csql/runtime/queryplanbuilder.h"
#include "csql/CSTableScan.h"
#include "csql/CSTableScanProvider.h"
#include "csql/runtime/defaultruntime.h"
#include "csql/runtime/tablerepository.h"

using namespace stx;
using namespace zbase;

stx::thread::EventLoop ev;

void cmd_cluster_status(const cli::FlagParser& flags) {
  ConfigDirectoryClient cclient(
      InetAddr::resolve(flags.getString("master")));

  auto cluster = cclient.fetchClusterConfig();
  iputs("Cluster config:\n$0", cluster.DebugString());
}

void cmd_cluster_add_node(const cli::FlagParser& flags) {
  ConfigDirectoryClient cclient(
      InetAddr::resolve(flags.getString("master")));

  auto cluster = cclient.fetchClusterConfig();
  auto node = cluster.add_dht_nodes();
  node->set_name(flags.getString("name"));
  node->set_addr(flags.getString("addr"));
  node->set_status(DHTNODE_LIVE);

  auto vnodes = flags.getInt("vnodes");
  for (size_t i = 0; i < vnodes; ++i) {
    auto token = Random::singleton()->sha1().toString();
    *node->add_sha1_tokens() = token;
  }

  cclient.updateClusterConfig(cluster);
}

void cmd_import_session_sstable(const cli::FlagParser& flags) {
  thread::EventLoop ev;

  auto evloop_thread = std::thread([&ev] {
    ev.run();
  });

  stx::logInfo(
      "analyticsctl",
      "Uploading sstable: $0",
      flags.getString("sstable"));

  http::HTTPConnectionPool http(&ev);
  zbase::TSDBClient tsdb("http://localhost:8000/tsdb", &http);

  sstable::SSTableReader reader(flags.getString("sstable"));
  auto cursor = reader.getCursor();

  auto batch_size = 100;
  zbase::RecordEnvelopeList batch;
  auto upload_batch = [&tsdb, &batch] {
    stx::logInfo(
        "analyticsctl",
        "Uploading $0 records...",
        batch.records_size());

    try {
      tsdb.insertRecords(batch);
      batch.clear_records();
    } catch (const Exception& e) {
      stx::logError("analyticsctl", e, "error while uploading records");
    }
  };

  size_t nrecs = 0;
  while (cursor->valid()) {
    auto record_id = SHA1::compute(cursor->getKeyBuffer());
    auto record_data = cursor->getDataBuffer();

    auto session = msg::decode<zbase::JoinedSession>(record_data);
    auto time = UnixTime(session.first_seen_time() * kMicrosPerSecond);
    if (time.unixMicros() == 0) {
      RAISE(kRuntimeError, "session has no time");
    }

    auto tsdb_ns = "dawanda";
    auto table_name = "logjoin.joined_sessions";
    auto partition_key = zbase::TimeWindowPartitioner::partitionKeyFor(
        table_name,
        time,
        4 * kMicrosPerHour);

    auto r = batch.add_records();
    r->set_tsdb_namespace(tsdb_ns);
    r->set_table_name(table_name);
    r->set_partition_sha1(partition_key.toString());
    r->set_record_id(record_id.toString());
    r->set_record_data(record_data.toString());

    if (batch.records_size() >= batch_size) {
      upload_batch();
    }

    ++nrecs;

    if (!cursor->next()) {
      break;
    }
  }

  upload_batch();

  stx::logInfo(
      "analyticsctl",
      "Finished uploading sstable: $0, $1 records",
      flags.getString("sstable"),
      nrecs);

  ev.shutdown();
  evloop_thread.join();
}

void cmd_backfill_session_sstable(const cli::FlagParser& flags) {
  thread::EventLoop ev;

  auto evloop_thread = std::thread([&ev] {
    ev.run();
  });

  stx::logInfo(
      "analyticsctl",
      "Uploading sstable: $0",
      flags.getString("sstable"));

  http::HTTPConnectionPool http(&ev);
  zbase::TSDBClient tsdb("http://nue05.prod.fnrd.net:7004/tsdb", &http);

  sstable::SSTableReader reader(flags.getString("sstable"));
  auto cursor = reader.getCursor();

  auto batch_size = 100;
  zbase::RecordEnvelopeList batch;
  auto upload_batch = [&tsdb, &batch] {
    stx::logInfo(
        "analyticsctl",
        "Uploading $0 records...",
        batch.records_size());

    try {
      tsdb.insertRecords(batch);
      batch.clear_records();
    } catch (const Exception& e) {
      stx::logError("analyticsctl", e, "error while uploading records");
    }
  };

  size_t nrecs = 0;
  auto tsdb_ns = "dawanda";
  auto table_name = String("sessions");
  while (cursor->valid()) {
    auto record_id = SHA1::compute(cursor->getKeyBuffer());
    auto record_data = cursor->getDataBuffer();

    auto old_session = msg::decode<zbase::JoinedSession>(record_data);
    if (old_session.last_seen_time() == 0) {
      RAISE(kRuntimeError, "last seen time is empty");
    }

    zbase::NewJoinedSession new_session;

    size_t n = 0;
    for (const auto& old_ev : old_session.search_queries()) {
      auto new_ev = new_session.mutable_event()->add_search_query();
      *new_ev = old_ev;

      new_ev->set_time(old_ev.time() * kMicrosPerSecond);

      auto evkey = table_name + ".search_query";
      auto evid = SHA1::compute(
          record_id.toString() + StringUtil::toString(++n));
      auto partition_key = zbase::TimeWindowPartitioner::partitionKeyFor(
          evkey,
          old_ev.time() * kMicrosPerSecond,
          4 * kMicrosPerHour);

      auto r = batch.add_records();
      r->set_tsdb_namespace(tsdb_ns);
      r->set_table_name(evkey);
      r->set_partition_sha1(partition_key.toString());
      r->set_record_id(evid.toString());
      r->set_record_data(msg::encode(*new_ev)->toString());
    }

    for (const auto& old_ev : old_session.page_views()) {
      auto new_ev = new_session.mutable_event()->add_page_view();
      *new_ev = old_ev;

      new_ev->set_time(old_ev.time() * kMicrosPerSecond);

      auto evkey = table_name + ".page_view";
      auto evid = SHA1::compute(
          record_id.toString() + StringUtil::toString(++n));
      auto partition_key = zbase::TimeWindowPartitioner::partitionKeyFor(
          evkey,
          old_ev.time() * kMicrosPerSecond,
          4 * kMicrosPerHour);

      auto r = batch.add_records();
      r->set_tsdb_namespace(tsdb_ns);
      r->set_table_name(evkey);
      r->set_partition_sha1(partition_key.toString());
      r->set_record_id(evid.toString());
      r->set_record_data(msg::encode(*new_ev)->toString());
    }

    for (const auto& old_ev : old_session.cart_items()) {
      auto new_ev = new_session.mutable_event()->add_cart_items();
      *new_ev = old_ev;

      new_ev->set_time(old_ev.time() * kMicrosPerSecond);

      auto evkey = table_name + ".cart_items";
      auto evid = SHA1::compute(
          record_id.toString() + StringUtil::toString(++n));
      auto partition_key = zbase::TimeWindowPartitioner::partitionKeyFor(
          evkey,
          old_ev.time() * kMicrosPerSecond,
          4 * kMicrosPerHour);

      auto r = batch.add_records();
      r->set_tsdb_namespace(tsdb_ns);
      r->set_table_name(evkey);
      r->set_partition_sha1(partition_key.toString());
      r->set_record_id(evid.toString());
      r->set_record_data(msg::encode(*new_ev)->toString());
    }

    new_session.set_session_id(SHA1::compute(cursor->getKeyString()).toString());
    new_session.set_time(old_session.last_seen_time() * kMicrosPerSecond);
    new_session.set_first_seen_time(old_session.first_seen_time() * kMicrosPerSecond);
    new_session.set_last_seen_time(old_session.last_seen_time() * kMicrosPerSecond);

    new_session.mutable_attr()->set_customer_session_id(old_session.customer_session_id());
    new_session.mutable_attr()->set_referrer_url(old_session.referrer_url());
    new_session.mutable_attr()->set_referrer_campaign(old_session.referrer_campaign());
    new_session.mutable_attr()->set_referrer_name(old_session.referrer_name());
    new_session.mutable_attr()->set_num_cart_items(old_session.num_cart_items());
    new_session.mutable_attr()->set_num_order_items(old_session.num_order_items());
    new_session.mutable_attr()->set_cart_value_eurcents(old_session.cart_value_eurcents());
    new_session.mutable_attr()->set_gmv_eurcents(old_session.gmv_eurcents());
    new_session.mutable_attr()->set_ab_test_group(old_session.ab_test_group());

    {
      auto time = UnixTime(old_session.last_seen_time() * kMicrosPerSecond);
      auto partition_key = zbase::TimeWindowPartitioner::partitionKeyFor(
          table_name,
          time,
          4 * kMicrosPerHour);

      auto r = batch.add_records();
      r->set_tsdb_namespace(tsdb_ns);
      r->set_table_name(table_name);
      r->set_partition_sha1(partition_key.toString());
      r->set_record_id(record_id.toString());
      r->set_record_data(msg::encode(new_session)->toString());
    }

    if (batch.records_size() >= batch_size) {
      upload_batch();
    }

    ++nrecs;

    if (!cursor->next()) {
      break;
    }
  }

  upload_batch();

  stx::logInfo(
      "analyticsctl",
      "Finished uploading sstable: $0, $1 records",
      flags.getString("sstable"),
      nrecs);

  ev.shutdown();
  evloop_thread.join();
}

int main(int argc, const char** argv) {
  stx::Application::init();
  stx::Application::logToStderr();

  stx::cli::FlagParser flags;

  flags.defineFlag(
      "loglevel",
      stx::cli::FlagParser::T_STRING,
      false,
      NULL,
      "INFO",
      "loglevel",
      "<level>");

  flags.parseArgv(argc, argv);

  Logger::get()->setMinimumLogLevel(
      strToLogLevel(flags.getString("loglevel")));

  cli::CLI cli;

  /* command: import */
  auto import_cmd = cli.defineCommand("import_session_sstable");
  import_cmd->onCall(std::bind(&cmd_import_session_sstable, std::placeholders::_1));

  import_cmd->flags().defineFlag(
      "sstable",
      stx::cli::FlagParser::T_STRING,
      true,
      NULL,
      NULL,
      "input file path",
      "<path>");

  /* command: backfill */
  auto backfill_cmd = cli.defineCommand("backfill_session_sstable");
  backfill_cmd->onCall(std::bind(&cmd_backfill_session_sstable, std::placeholders::_1));

  backfill_cmd->flags().defineFlag(
      "sstable",
      stx::cli::FlagParser::T_STRING,
      true,
      NULL,
      NULL,
      "input file path",
      "<path>");

  /* command: cluster_status */
  auto cluster_status_cmd = cli.defineCommand("cluster_status");
  cluster_status_cmd->onCall(
      std::bind(&cmd_cluster_status, std::placeholders::_1));

  cluster_status_cmd->flags().defineFlag(
      "master",
      cli::FlagParser::T_STRING,
      true,
      NULL,
      NULL,
      "url",
      "<addr>");

  /* command: cluster_add_node */
  auto cluster_add_node_cmd = cli.defineCommand("cluster_add_node");
  cluster_add_node_cmd->onCall(
      std::bind(&cmd_cluster_add_node, std::placeholders::_1));

  cluster_add_node_cmd->flags().defineFlag(
      "master",
      cli::FlagParser::T_STRING,
      true,
      NULL,
      NULL,
      "url",
      "<addr>");

  cluster_add_node_cmd->flags().defineFlag(
      "name",
      stx::cli::FlagParser::T_STRING,
      true,
      NULL,
      NULL,
      "node name",
      "<string>");

  cluster_add_node_cmd->flags().defineFlag(
      "addr",
      stx::cli::FlagParser::T_STRING,
      true,
      NULL,
      NULL,
      "node address",
      "<ip:port>");

  cluster_add_node_cmd->flags().defineFlag(
      "vnodes",
      stx::cli::FlagParser::T_INTEGER,
      true,
      NULL,
      NULL,
      "number of vnodes to assign",
      "<num>");

  cli.call(flags.getArgv());
  return 0;
}

<commit_msg>use dashes in command names<commit_after>/**
 * Copyright (c) 2015 - The CM Authors <legal@clickmatcher.com>
 *   All Rights Reserved.
 *
 * This file is CONFIDENTIAL -- Distribution or duplication of this material or
 * the information contained herein is strictly forbidden unless prior written
 * permission is obtained.
 */
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>
#include "stx/io/filerepository.h"
#include "stx/io/fileutil.h"
#include "stx/application.h"
#include "stx/logging.h"
#include "stx/random.h"
#include "stx/thread/eventloop.h"
#include "stx/thread/threadpool.h"
#include "stx/thread/FixedSizeThreadPool.h"
#include "stx/wallclock.h"
#include "stx/VFS.h"
#include "stx/cli/flagparser.h"
#include "stx/json/json.h"
#include "stx/json/jsonrpc.h"
#include "stx/http/httprouter.h"
#include "stx/http/httpserver.h"
#include "stx/http/httpconnectionpool.h"
#include "stx/http/VFSFileServlet.h"
#include "stx/cli/CLI.h"
#include "stx/cli/flagparser.h"
#include "zbase/dproc/LocalScheduler.h"
#include "zbase/dproc/DispatchService.h"
#include "zbase/ConfigDirectory.h"
#include "sstable/sstablereader.h"
#include "zbase/JoinedSession.pb.h"
#include "zbase/core/TimeWindowPartitioner.h"
#include "zbase/core/TSDBClient.h"
#include "csql/qtree/SequentialScanNode.h"
#include "csql/qtree/ColumnReferenceNode.h"
#include "csql/qtree/CallExpressionNode.h"
#include "csql/qtree/GroupByNode.h"
#include "csql/qtree/UnionNode.h"
#include "csql/runtime/queryplanbuilder.h"
#include "csql/CSTableScan.h"
#include "csql/CSTableScanProvider.h"
#include "csql/runtime/defaultruntime.h"
#include "csql/runtime/tablerepository.h"

using namespace stx;
using namespace zbase;

stx::thread::EventLoop ev;

void cmd_cluster_status(const cli::FlagParser& flags) {
  ConfigDirectoryClient cclient(
      InetAddr::resolve(flags.getString("master")));

  auto cluster = cclient.fetchClusterConfig();
  iputs("Cluster config:\n$0", cluster.DebugString());
}

void cmd_cluster_add_node(const cli::FlagParser& flags) {
  ConfigDirectoryClient cclient(
      InetAddr::resolve(flags.getString("master")));

  auto cluster = cclient.fetchClusterConfig();
  auto node = cluster.add_dht_nodes();
  node->set_name(flags.getString("name"));
  node->set_addr(flags.getString("addr"));
  node->set_status(DHTNODE_LIVE);

  auto vnodes = flags.getInt("vnodes");
  for (size_t i = 0; i < vnodes; ++i) {
    auto token = Random::singleton()->sha1().toString();
    *node->add_sha1_tokens() = token;
  }

  cclient.updateClusterConfig(cluster);
}

void cmd_import_session_sstable(const cli::FlagParser& flags) {
  thread::EventLoop ev;

  auto evloop_thread = std::thread([&ev] {
    ev.run();
  });

  stx::logInfo(
      "analyticsctl",
      "Uploading sstable: $0",
      flags.getString("sstable"));

  http::HTTPConnectionPool http(&ev);
  zbase::TSDBClient tsdb("http://localhost:8000/tsdb", &http);

  sstable::SSTableReader reader(flags.getString("sstable"));
  auto cursor = reader.getCursor();

  auto batch_size = 100;
  zbase::RecordEnvelopeList batch;
  auto upload_batch = [&tsdb, &batch] {
    stx::logInfo(
        "analyticsctl",
        "Uploading $0 records...",
        batch.records_size());

    try {
      tsdb.insertRecords(batch);
      batch.clear_records();
    } catch (const Exception& e) {
      stx::logError("analyticsctl", e, "error while uploading records");
    }
  };

  size_t nrecs = 0;
  while (cursor->valid()) {
    auto record_id = SHA1::compute(cursor->getKeyBuffer());
    auto record_data = cursor->getDataBuffer();

    auto session = msg::decode<zbase::JoinedSession>(record_data);
    auto time = UnixTime(session.first_seen_time() * kMicrosPerSecond);
    if (time.unixMicros() == 0) {
      RAISE(kRuntimeError, "session has no time");
    }

    auto tsdb_ns = "dawanda";
    auto table_name = "logjoin.joined_sessions";
    auto partition_key = zbase::TimeWindowPartitioner::partitionKeyFor(
        table_name,
        time,
        4 * kMicrosPerHour);

    auto r = batch.add_records();
    r->set_tsdb_namespace(tsdb_ns);
    r->set_table_name(table_name);
    r->set_partition_sha1(partition_key.toString());
    r->set_record_id(record_id.toString());
    r->set_record_data(record_data.toString());

    if (batch.records_size() >= batch_size) {
      upload_batch();
    }

    ++nrecs;

    if (!cursor->next()) {
      break;
    }
  }

  upload_batch();

  stx::logInfo(
      "analyticsctl",
      "Finished uploading sstable: $0, $1 records",
      flags.getString("sstable"),
      nrecs);

  ev.shutdown();
  evloop_thread.join();
}

void cmd_backfill_session_sstable(const cli::FlagParser& flags) {
  thread::EventLoop ev;

  auto evloop_thread = std::thread([&ev] {
    ev.run();
  });

  stx::logInfo(
      "analyticsctl",
      "Uploading sstable: $0",
      flags.getString("sstable"));

  http::HTTPConnectionPool http(&ev);
  zbase::TSDBClient tsdb("http://nue05.prod.fnrd.net:7004/tsdb", &http);

  sstable::SSTableReader reader(flags.getString("sstable"));
  auto cursor = reader.getCursor();

  auto batch_size = 100;
  zbase::RecordEnvelopeList batch;
  auto upload_batch = [&tsdb, &batch] {
    stx::logInfo(
        "analyticsctl",
        "Uploading $0 records...",
        batch.records_size());

    try {
      tsdb.insertRecords(batch);
      batch.clear_records();
    } catch (const Exception& e) {
      stx::logError("analyticsctl", e, "error while uploading records");
    }
  };

  size_t nrecs = 0;
  auto tsdb_ns = "dawanda";
  auto table_name = String("sessions");
  while (cursor->valid()) {
    auto record_id = SHA1::compute(cursor->getKeyBuffer());
    auto record_data = cursor->getDataBuffer();

    auto old_session = msg::decode<zbase::JoinedSession>(record_data);
    if (old_session.last_seen_time() == 0) {
      RAISE(kRuntimeError, "last seen time is empty");
    }

    zbase::NewJoinedSession new_session;

    size_t n = 0;
    for (const auto& old_ev : old_session.search_queries()) {
      auto new_ev = new_session.mutable_event()->add_search_query();
      *new_ev = old_ev;

      new_ev->set_time(old_ev.time() * kMicrosPerSecond);

      auto evkey = table_name + ".search_query";
      auto evid = SHA1::compute(
          record_id.toString() + StringUtil::toString(++n));
      auto partition_key = zbase::TimeWindowPartitioner::partitionKeyFor(
          evkey,
          old_ev.time() * kMicrosPerSecond,
          4 * kMicrosPerHour);

      auto r = batch.add_records();
      r->set_tsdb_namespace(tsdb_ns);
      r->set_table_name(evkey);
      r->set_partition_sha1(partition_key.toString());
      r->set_record_id(evid.toString());
      r->set_record_data(msg::encode(*new_ev)->toString());
    }

    for (const auto& old_ev : old_session.page_views()) {
      auto new_ev = new_session.mutable_event()->add_page_view();
      *new_ev = old_ev;

      new_ev->set_time(old_ev.time() * kMicrosPerSecond);

      auto evkey = table_name + ".page_view";
      auto evid = SHA1::compute(
          record_id.toString() + StringUtil::toString(++n));
      auto partition_key = zbase::TimeWindowPartitioner::partitionKeyFor(
          evkey,
          old_ev.time() * kMicrosPerSecond,
          4 * kMicrosPerHour);

      auto r = batch.add_records();
      r->set_tsdb_namespace(tsdb_ns);
      r->set_table_name(evkey);
      r->set_partition_sha1(partition_key.toString());
      r->set_record_id(evid.toString());
      r->set_record_data(msg::encode(*new_ev)->toString());
    }

    for (const auto& old_ev : old_session.cart_items()) {
      auto new_ev = new_session.mutable_event()->add_cart_items();
      *new_ev = old_ev;

      new_ev->set_time(old_ev.time() * kMicrosPerSecond);

      auto evkey = table_name + ".cart_items";
      auto evid = SHA1::compute(
          record_id.toString() + StringUtil::toString(++n));
      auto partition_key = zbase::TimeWindowPartitioner::partitionKeyFor(
          evkey,
          old_ev.time() * kMicrosPerSecond,
          4 * kMicrosPerHour);

      auto r = batch.add_records();
      r->set_tsdb_namespace(tsdb_ns);
      r->set_table_name(evkey);
      r->set_partition_sha1(partition_key.toString());
      r->set_record_id(evid.toString());
      r->set_record_data(msg::encode(*new_ev)->toString());
    }

    new_session.set_session_id(SHA1::compute(cursor->getKeyString()).toString());
    new_session.set_time(old_session.last_seen_time() * kMicrosPerSecond);
    new_session.set_first_seen_time(old_session.first_seen_time() * kMicrosPerSecond);
    new_session.set_last_seen_time(old_session.last_seen_time() * kMicrosPerSecond);

    new_session.mutable_attr()->set_customer_session_id(old_session.customer_session_id());
    new_session.mutable_attr()->set_referrer_url(old_session.referrer_url());
    new_session.mutable_attr()->set_referrer_campaign(old_session.referrer_campaign());
    new_session.mutable_attr()->set_referrer_name(old_session.referrer_name());
    new_session.mutable_attr()->set_num_cart_items(old_session.num_cart_items());
    new_session.mutable_attr()->set_num_order_items(old_session.num_order_items());
    new_session.mutable_attr()->set_cart_value_eurcents(old_session.cart_value_eurcents());
    new_session.mutable_attr()->set_gmv_eurcents(old_session.gmv_eurcents());
    new_session.mutable_attr()->set_ab_test_group(old_session.ab_test_group());

    {
      auto time = UnixTime(old_session.last_seen_time() * kMicrosPerSecond);
      auto partition_key = zbase::TimeWindowPartitioner::partitionKeyFor(
          table_name,
          time,
          4 * kMicrosPerHour);

      auto r = batch.add_records();
      r->set_tsdb_namespace(tsdb_ns);
      r->set_table_name(table_name);
      r->set_partition_sha1(partition_key.toString());
      r->set_record_id(record_id.toString());
      r->set_record_data(msg::encode(new_session)->toString());
    }

    if (batch.records_size() >= batch_size) {
      upload_batch();
    }

    ++nrecs;

    if (!cursor->next()) {
      break;
    }
  }

  upload_batch();

  stx::logInfo(
      "analyticsctl",
      "Finished uploading sstable: $0, $1 records",
      flags.getString("sstable"),
      nrecs);

  ev.shutdown();
  evloop_thread.join();
}

int main(int argc, const char** argv) {
  stx::Application::init();
  stx::Application::logToStderr();

  stx::cli::FlagParser flags;

  flags.defineFlag(
      "loglevel",
      stx::cli::FlagParser::T_STRING,
      false,
      NULL,
      "INFO",
      "loglevel",
      "<level>");

  flags.parseArgv(argc, argv);

  Logger::get()->setMinimumLogLevel(
      strToLogLevel(flags.getString("loglevel")));

  cli::CLI cli;

  /* command: import */
  auto import_cmd = cli.defineCommand("import_session_sstable");
  import_cmd->onCall(std::bind(&cmd_import_session_sstable, std::placeholders::_1));

  import_cmd->flags().defineFlag(
      "sstable",
      stx::cli::FlagParser::T_STRING,
      true,
      NULL,
      NULL,
      "input file path",
      "<path>");

  /* command: backfill */
  auto backfill_cmd = cli.defineCommand("backfill_session_sstable");
  backfill_cmd->onCall(std::bind(&cmd_backfill_session_sstable, std::placeholders::_1));

  backfill_cmd->flags().defineFlag(
      "sstable",
      stx::cli::FlagParser::T_STRING,
      true,
      NULL,
      NULL,
      "input file path",
      "<path>");

  /* command: cluster_status */
  auto cluster_status_cmd = cli.defineCommand("cluster-status");
  cluster_status_cmd->onCall(
      std::bind(&cmd_cluster_status, std::placeholders::_1));

  cluster_status_cmd->flags().defineFlag(
      "master",
      cli::FlagParser::T_STRING,
      true,
      NULL,
      NULL,
      "url",
      "<addr>");

  /* command: cluster_add_node */
  auto cluster_add_node_cmd = cli.defineCommand("cluster-add-node");
  cluster_add_node_cmd->onCall(
      std::bind(&cmd_cluster_add_node, std::placeholders::_1));

  cluster_add_node_cmd->flags().defineFlag(
      "master",
      cli::FlagParser::T_STRING,
      true,
      NULL,
      NULL,
      "url",
      "<addr>");

  cluster_add_node_cmd->flags().defineFlag(
      "name",
      stx::cli::FlagParser::T_STRING,
      true,
      NULL,
      NULL,
      "node name",
      "<string>");

  cluster_add_node_cmd->flags().defineFlag(
      "addr",
      stx::cli::FlagParser::T_STRING,
      true,
      NULL,
      NULL,
      "node address",
      "<ip:port>");

  cluster_add_node_cmd->flags().defineFlag(
      "vnodes",
      stx::cli::FlagParser::T_INTEGER,
      true,
      NULL,
      NULL,
      "number of vnodes to assign",
      "<num>");

  cli.call(flags.getArgv());
  return 0;
}

<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: streamsection.cxx,v $
 *
 *  $Revision: 1.5 $
 *
 *  last change: $Author: rt $ $Date: 2005-09-08 03:01:19 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/

#ifndef _COMPHELPER_STREAMSECTION_HXX_
#include <comphelper/streamsection.hxx>
#endif

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

namespace comphelper
{

//-------------------------------------------------------------------------
OStreamSection::OStreamSection(const staruno::Reference< stario::XDataInputStream >& _rxInput)
    :m_xMarkStream(_rxInput, ::com::sun::star::uno::UNO_QUERY)
    ,m_xInStream(_rxInput)
    ,m_nBlockStart(-1)
    ,m_nBlockLen(-1)
{
    OSL_ENSURE(m_xInStream.is() && m_xMarkStream.is(), "OStreamSection::OStreamSection : invalid argument !");
    if (m_xInStream.is() && m_xMarkStream.is())
    {
        m_nBlockLen = _rxInput->readLong();
        m_nBlockStart = m_xMarkStream->createMark();
    }
}

//-------------------------------------------------------------------------
OStreamSection::OStreamSection(const staruno::Reference< stario::XDataOutputStream >& _rxOutput, sal_Int32 _nPresumedLength)
    :m_xMarkStream(_rxOutput, ::com::sun::star::uno::UNO_QUERY)
    ,m_xOutStream(_rxOutput)
    ,m_nBlockStart(-1)
    ,m_nBlockLen(-1)
{
    OSL_ENSURE(m_xOutStream.is() && m_xMarkStream.is(), "OStreamSection::OStreamSection : invalid argument !");
    if (m_xOutStream.is() && m_xMarkStream.is())
    {
        m_nBlockStart = m_xMarkStream->createMark();
        // a placeholder where we will write the overall length (within the destructor)
        if (_nPresumedLength > 0)
            m_nBlockLen = _nPresumedLength + sizeof(m_nBlockLen);
            // as the caller did not consider - of course - the placeholder we are going to write
        else
            m_nBlockLen = 0;
        m_xOutStream->writeLong(m_nBlockLen);
    }
}

//-------------------------------------------------------------------------
OStreamSection::~OStreamSection()
{
    try
    {   // don't allow any exceptions to leave this block, this may be called during the stack unwinding of an exception
        // handling routing
        if (m_xInStream.is() &&  m_xMarkStream.is())
        {   // we're working on an input stream
            m_xMarkStream->jumpToMark(m_nBlockStart);
            m_xInStream->skipBytes(m_nBlockLen);
            m_xMarkStream->deleteMark(m_nBlockStart);
        }
        else if (m_xOutStream.is() && m_xMarkStream.is())
        {
            sal_Int32 nRealBlockLength = m_xMarkStream->offsetToMark(m_nBlockStart) - sizeof(m_nBlockLen);
            if (m_nBlockLen && (m_nBlockLen == nRealBlockLength))
                // nothing to do : the estimation the caller gave us (in the ctor) was correct
                m_xMarkStream->deleteMark(m_nBlockStart);
            else
            {   // the estimation was wrong (or we didn't get one)
                m_nBlockLen = nRealBlockLength;
                m_xMarkStream->jumpToMark(m_nBlockStart);
                m_xOutStream->writeLong(m_nBlockLen);
                m_xMarkStream->jumpToFurthest();
                m_xMarkStream->deleteMark(m_nBlockStart);
            }
        }
    }
    catch(const staruno::Exception&)
    {
    }
}
// -----------------------------------------------------------------------------
sal_Int32 OStreamSection::available()
{
    sal_Int32 nBytes = 0;
    try
    {   // don't allow any exceptions to leave this block, this may be called during the stack unwinding of an exception
        if (m_xInStream.is() &&  m_xMarkStream.is())
            nBytes = m_xMarkStream->offsetToMark(m_nBlockStart) - sizeof(m_nBlockLen);
    }
    catch(const staruno::Exception&)
    {
    }
    return nBytes;
}
// -----------------------------------------------------------------------------

}   // namespace comphelper

<commit_msg>INTEGRATION: CWS pchfix02 (1.5.100); FILE MERGED 2006/09/01 17:19:49 kaib 1.5.100.1: #i68856# Added header markers and pch files<commit_after>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: streamsection.cxx,v $
 *
 *  $Revision: 1.6 $
 *
 *  last change: $Author: obo $ $Date: 2006-09-17 17:21:36 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/

// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_comphelper.hxx"

#ifndef _COMPHELPER_STREAMSECTION_HXX_
#include <comphelper/streamsection.hxx>
#endif

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

namespace comphelper
{

//-------------------------------------------------------------------------
OStreamSection::OStreamSection(const staruno::Reference< stario::XDataInputStream >& _rxInput)
    :m_xMarkStream(_rxInput, ::com::sun::star::uno::UNO_QUERY)
    ,m_xInStream(_rxInput)
    ,m_nBlockStart(-1)
    ,m_nBlockLen(-1)
{
    OSL_ENSURE(m_xInStream.is() && m_xMarkStream.is(), "OStreamSection::OStreamSection : invalid argument !");
    if (m_xInStream.is() && m_xMarkStream.is())
    {
        m_nBlockLen = _rxInput->readLong();
        m_nBlockStart = m_xMarkStream->createMark();
    }
}

//-------------------------------------------------------------------------
OStreamSection::OStreamSection(const staruno::Reference< stario::XDataOutputStream >& _rxOutput, sal_Int32 _nPresumedLength)
    :m_xMarkStream(_rxOutput, ::com::sun::star::uno::UNO_QUERY)
    ,m_xOutStream(_rxOutput)
    ,m_nBlockStart(-1)
    ,m_nBlockLen(-1)
{
    OSL_ENSURE(m_xOutStream.is() && m_xMarkStream.is(), "OStreamSection::OStreamSection : invalid argument !");
    if (m_xOutStream.is() && m_xMarkStream.is())
    {
        m_nBlockStart = m_xMarkStream->createMark();
        // a placeholder where we will write the overall length (within the destructor)
        if (_nPresumedLength > 0)
            m_nBlockLen = _nPresumedLength + sizeof(m_nBlockLen);
            // as the caller did not consider - of course - the placeholder we are going to write
        else
            m_nBlockLen = 0;
        m_xOutStream->writeLong(m_nBlockLen);
    }
}

//-------------------------------------------------------------------------
OStreamSection::~OStreamSection()
{
    try
    {   // don't allow any exceptions to leave this block, this may be called during the stack unwinding of an exception
        // handling routing
        if (m_xInStream.is() &&  m_xMarkStream.is())
        {   // we're working on an input stream
            m_xMarkStream->jumpToMark(m_nBlockStart);
            m_xInStream->skipBytes(m_nBlockLen);
            m_xMarkStream->deleteMark(m_nBlockStart);
        }
        else if (m_xOutStream.is() && m_xMarkStream.is())
        {
            sal_Int32 nRealBlockLength = m_xMarkStream->offsetToMark(m_nBlockStart) - sizeof(m_nBlockLen);
            if (m_nBlockLen && (m_nBlockLen == nRealBlockLength))
                // nothing to do : the estimation the caller gave us (in the ctor) was correct
                m_xMarkStream->deleteMark(m_nBlockStart);
            else
            {   // the estimation was wrong (or we didn't get one)
                m_nBlockLen = nRealBlockLength;
                m_xMarkStream->jumpToMark(m_nBlockStart);
                m_xOutStream->writeLong(m_nBlockLen);
                m_xMarkStream->jumpToFurthest();
                m_xMarkStream->deleteMark(m_nBlockStart);
            }
        }
    }
    catch(const staruno::Exception&)
    {
    }
}
// -----------------------------------------------------------------------------
sal_Int32 OStreamSection::available()
{
    sal_Int32 nBytes = 0;
    try
    {   // don't allow any exceptions to leave this block, this may be called during the stack unwinding of an exception
        if (m_xInStream.is() &&  m_xMarkStream.is())
            nBytes = m_xMarkStream->offsetToMark(m_nBlockStart) - sizeof(m_nBlockLen);
    }
    catch(const staruno::Exception&)
    {
    }
    return nBytes;
}
// -----------------------------------------------------------------------------

}   // namespace comphelper

<|endoftext|>


<commit_before>#pragma once

#include <string>
#include <string_view>
#include <vector>
#include <tuple>
#include <cstdio>
#include <cmath>

// ----------------------------------------------------------------------

namespace acmacs
{
    // template <typename T> inline std::string to_string(T aSrc)
    // {
    //     return std::to_string(aSrc);
    // }

    inline std::string to_string(int src) { return std::to_string(src); }
    inline std::string to_string(unsigned src) { return std::to_string(src); }
    inline std::string to_string(long src) { return std::to_string(src); }
    inline std::string to_string(unsigned long src) { return std::to_string(src); }
    inline std::string to_string(float src) { return std::to_string(src); }
    inline std::string to_string(char src) { return std::string(1, src); }

    inline std::string to_string(double value, int precision = 32)
    {
        const auto num_digits_before_dot = static_cast<int>(std::log10(std::abs(value))) + 1;
        constexpr const size_t buffer_size = 100;
        char buffer[buffer_size + 1];
        const int written = std::snprintf(buffer, buffer_size, "%.*g", precision + num_digits_before_dot, value);
        if (written < 0 && static_cast<size_t>(written) >= buffer_size)
            throw std::runtime_error("acmacs::to_string(double) internal error");
        return {buffer, static_cast<size_t>(written)};
    }

    inline std::string to_string(std::string src) { return src; }
    inline std::string to_string(std::string_view src) { return std::string(src); }
    inline std::string to_string(const char* src) { return src; }

    template <typename L, typename R> inline std::string to_string(const std::pair<L, R>& arg)
    {
        std::string result{'<'};
        result += to_string(arg.first);
        result += ", ";
        result += to_string(arg.second);
        result += '>';
        return result;
    }

    template <typename Iter, typename ... Args> inline std::string to_string(Iter first, Iter last, Args&& ... args)
    {
        std::string result{'['};
        while (first != last) {
            if (result.size() > 1)
                result += ", ";
            result += to_string(*first, std::forward<Args>(args) ...);
            ++first;
        }
        result += "]";
        return result;
    }

    template <typename Element, typename ... Args> inline std::string to_string(const std::vector<Element>& src, Args&& ... args)
    {
        return to_string(src.begin(), src.end(), std::forward<Args>(args) ...);
    }

} // namespace acmacs

// ----------------------------------------------------------------------
/// Local Variables:
/// eval: (if (fboundp 'eu-rename-buffer) (eu-rename-buffer))
/// End:
<commit_msg>acmacs::string::split_into_double improvements<commit_after>#pragma once

#include <string>
#include <string_view>
#include <vector>
#include <tuple>
#include <cstdio>
#include <cmath>

// ----------------------------------------------------------------------

namespace acmacs
{
    // template <typename T> inline std::string to_string(T aSrc)
    // {
    //     return std::to_string(aSrc);
    // }

    inline std::string to_string(int src) { return std::to_string(src); }
    inline std::string to_string(unsigned src) { return std::to_string(src); }
    inline std::string to_string(long src) { return std::to_string(src); }
    inline std::string to_string(unsigned long src) { return std::to_string(src); }
    inline std::string to_string(long long src) { return std::to_string(src); }
    inline std::string to_string(unsigned long long src) { return std::to_string(src); }
    inline std::string to_string(float src) { return std::to_string(src); }
    inline std::string to_string(char src) { return std::string(1, src); }

#pragma GCC diagnostic push
#ifdef __clang__
#pragma GCC diagnostic ignored "-Wformat-nonliteral"
#endif
    namespace internal
    {
        template <typename D> inline std::string to_string_double(D value, int precision, const char* format)
        {
            const auto num_digits_before_dot = static_cast<int>(std::log10(std::abs(value))) + 1;
            constexpr const size_t buffer_size = 100;
            char buffer[buffer_size + 1];
            const int written = std::snprintf(buffer, buffer_size, format, precision + num_digits_before_dot, value);
            if (written < 0 && static_cast<size_t>(written) >= buffer_size)
                throw std::runtime_error("acmacs::to_string(double) internal error");
            return {buffer, static_cast<size_t>(written)};
        }
    } // namespace internal
#pragma GCC diagnostic pop

    inline std::string to_string(double value, int precision = 32) { return internal::to_string_double(value, precision, "%.*g"); }
    inline std::string to_string(long double value, int precision = 64) { return internal::to_string_double(value, precision, "%.*Lg"); }

    inline std::string to_string(std::string src) { return src; }
    inline std::string to_string(std::string_view src) { return std::string(src); }
    inline std::string to_string(const char* src) { return src; }

    template <typename L, typename R> inline std::string to_string(const std::pair<L, R>& arg)
    {
        std::string result{'<'};
        result += to_string(arg.first);
        result += ", ";
        result += to_string(arg.second);
        result += '>';
        return result;
    }

    template <typename Iter, typename ... Args> inline std::string to_string(Iter first, Iter last, Args&& ... args)
    {
        std::string result{'['};
        while (first != last) {
            if (result.size() > 1)
                result += ", ";
            result += to_string(*first, std::forward<Args>(args) ...);
            ++first;
        }
        result += "]";
        return result;
    }

    template <typename Element, typename ... Args> inline std::string to_string(const std::vector<Element>& src, Args&& ... args)
    {
        return to_string(src.begin(), src.end(), std::forward<Args>(args) ...);
    }

} // namespace acmacs

// ----------------------------------------------------------------------
/// Local Variables:
/// eval: (if (fboundp 'eu-rename-buffer) (eu-rename-buffer))
/// End:
<|endoftext|>


<commit_before>/**
 * @file Application.cpp
 *
 * @author Jan Dušek <xdusek17@stud.fit.vutbr.cz>
 * @date 2013
 */

#include "Application.h"

#include "Logging.h"
#include "Helpers.h"
#include "Common.h"
#include "Renderer.h"
#include "Scene.h"
#include "Node.h"
#include "ShaderManager.h"
#include "FpsCamera.h"
#include "Light.h"

#include "Cube.h"

#include <GL/glew.h>
#include <glm/gtc/matrix_transform.hpp>

#include <sstream>

const char* SDLApplication::DEFAULT_WND_TITLE = "Test app";

SDLApplication::SDLApplication(int argc, char** argv)
	: window(nullptr), context(nullptr), done(false), fps(60.0), windowTitle(DEFAULT_WND_TITLE),
	  renderer(new gl::Renderer())
{
	if (SDL_Init(SDL_INIT_VIDEO) != 0)
		throw SDLException("SDL_Init failed");

	createWindow(windowTitle, 800, 600);
}

SDLApplication::~SDLApplication() {
	SDL_GL_DeleteContext(context);
	SDL_DestroyWindow(window);
	SDL_Quit();
}

int SDLApplication::run() {
	init();

	uint64_t frameCount = 0;
	double prevTime = getTime();
	while (!done) {
		calculateFps(fps, prevTime, frameCount);
		processEvents();
		update();
		draw();
	}

	return 0;
}

void SDLApplication::setWindowTitle(const char* title) {
	if (title == nullptr)
		windowTitle = DEFAULT_WND_TITLE;
	else
		windowTitle = title;

	SDL_SetWindowTitle(window, windowTitle);
}

void SDLApplication::createWindow(const char* windowCaption, size_t width, size_t height) {
	this->width = width;
	this->height = height;

	// Set double buffering
	SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);

	// Create window
	window = SDL_CreateWindow(windowCaption, SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED,
		width, height, SDL_WINDOW_OPENGL);
	if (window == nullptr)
		throw SDLException("SDL_CreateWindow failed");

	context = SDL_GL_CreateContext(window);

	LOG(INFO) << "OpenGL version: " << glGetString(GL_VERSION);

	// Init GLEW
	GLenum err;
	glewExperimental = GL_TRUE;
	if ((err = glewInit()) != GLEW_OK)
		throw Exception((const char*)glewGetErrorString(err));

	LOG(INFO) << "Using GLEW " << glewGetString(GLEW_VERSION);

	// GL_EXT_direct_state_access detection broken in glew on my amd radeon 6630m
	// TODO: check if desired functions are not null manually
	/*if (!GLEW_EXT_direct_state_access)
		throw Exception("Missing EXT_direct_state_access extension!");*/

	grabMouse(true);
}

void SDLApplication::init() {
	renderer->setViewport(Viewport(static_cast<float>(width), static_cast<float>(height)));

	scene = std::unique_ptr<Scene>(new Scene(renderer.get()));

	auto material = std::make_shared<PhongMaterial>(renderer.get());
	ShaderManager shaderManager;
	material->setShader(shaderManager.getGlslProgram("phong"));

	PhongMaterialData materialData = { glm::vec4(0.0f, 0.1f, 0.0f, 1.0f),
		glm::vec4(0.8f, 0.3f, 0.1f, 1.0f), glm::vec4(0.3f, 0.3f, 0.3f, 1.0f), 5.0f };

	material->properties()->setData(materialData);
	material->properties()->flushData();

	auto mesh = std::make_shared<Mesh>();
	mesh->setPrimitiveType(PrimitiveType::TriangleList);

	std::vector<char> vertices(reinterpret_cast<const char*>(cubeVertices),
		reinterpret_cast<const char*>(cubeVertices) + sizeof(cubeVertices));
	std::vector<VertexElement> layout = create_vector<VertexElement>
		(VertexElement(3, VertexElementType::Float))(VertexElement(3, VertexElementType::Float));
	mesh->loadVertices(vertices, cubeVerticesCount, layout);

	std::vector<uint32_t> indices(reinterpret_cast<const unsigned*>(cubeIndices),
		reinterpret_cast<const unsigned*>(cubeIndices) + cubeIndicesCount);
	mesh->loadIndices(indices);

	scene->addNode(std::unique_ptr<Node>(new Node(mesh, material)));

	camera = std::unique_ptr<FpsCamera>(new FpsCamera(renderer.get()));
	camera->setProjectionMatrix(glm::perspective(90.0f, (float)width / height, 0.01f, 1000.0f));
	camera->setPosition(-3.0f, 0.0f, 0.5f);
	camera->setMovementSpeed(2.0f);

	renderer->setCamera(camera.get());

	light = std::unique_ptr<Light>(new Light(renderer.get()));
	light->setPosition(glm::vec4(-1.0f, 0.0f, 5.0f, 1.0f));
	light->setAmbient(glm::vec4(1.0f, 1.0f, 1.0f, 1.0f));
	light->setDiffuse(glm::vec4(1.0f, 1.0f, 1.0f, 1.0f));
	light->setSpecular(glm::vec4(1.0f, 1.0f, 1.0f, 1.0f));
	light->flushChanges();

	renderer->setLight(light.get());
}

void SDLApplication::update() {
	std::ostringstream ss;
	ss << windowTitle << " - " << fps;
	SDL_SetWindowTitle(window, ss.str().c_str());

	handleKeyboard();

	camera->update();
}

void SDLApplication::draw() {

	renderer->drawFrame();

	SDL_GL_SwapWindow(window);
}

void SDLApplication::processEvents() {
	SDL_Event event;
	while(SDL_PollEvent(&event)) {
		switch (event.type)
		{
		case SDL_QUIT:
			done = true;
			break;

		case SDL_KEYUP:
		case SDL_KEYDOWN:
			keyboardHandler.handleEvent(event.key);
			break;

		case SDL_MOUSEMOTION:
			handleMouseMove(event.motion.xrel, event.motion.yrel);
			break;
		}
	}
}

void SDLApplication::handleKeyboard() {
	if (keyboardHandler.isPressed(SDLK_ESCAPE)) {
		SDL_Event quitEvent = { SDL_QUIT };
		SDL_PushEvent(&quitEvent);
		return;
	}

	if (keyboardHandler.isPressed(SDLK_LALT)) {
		grabMouse(!mouseGrabbed);
	}

	if (keyboardHandler.isPressed(SDLK_w))
		camera->goForward(fps);
	if (keyboardHandler.isPressed(SDLK_s))
		camera->goBackward(fps);
	if (keyboardHandler.isPressed(SDLK_a))
		camera->goLeft(fps);
	if (keyboardHandler.isPressed(SDLK_d))
		camera->goRight(fps);
}

void SDLApplication::handleMouseMove(int xrel, int yrel) {
	/*int winWidth, winHeight;
	SDL_GetWindowSize(window, &winWidth, &winHeight);*/

	camera->yaw(static_cast<float>(xrel));
	camera->pitch(static_cast<float>(yrel));
}

void SDLApplication::grabMouse(bool flag) {
	if (SDL_SetRelativeMouseMode(flag ? SDL_TRUE : SDL_FALSE) == -1) {
		LOG(ERROR) << "SDL_SetRelativeMouseMode failed: " << SDL_GetError();
		mouseGrabbed = false;
		return;
	}
	mouseGrabbed = flag;
}

void SDLApplication::calculateFps(float& fps, double& prevTime, uint64_t& frameCount) {
	frameCount++;

	double currentTime = getTime();
	double timeInterval = currentTime - prevTime;
	if (timeInterval > 1.0) {
		fps = static_cast<float>(frameCount / timeInterval);
		prevTime = currentTime;
		frameCount = 0;
	}
}

double SDLApplication::getTime() {
#ifdef _WIN32
	// windows version
	static LARGE_INTEGER freq;
	static bool first = true;
	if (first) {
		first = false;
		if (!QueryPerformanceFrequency(&freq))
			throw Win32Exception("QueryPerformanceFrequency failed!");
	}

	LARGE_INTEGER val;
	QueryPerformanceCounter(&val);
	return static_cast<double>(val.QuadPart) / static_cast<double>(freq.QuadPart);
#else
	// posix version
	struct timeval tv;
	if (gettimeofday(&tv, NULL) == -1)
		throw SystemException("gettimeofday failed!");

	return static_cast<double>(tv.tv_sec) + static_cast<double>(tv.tv_usec) / 1000000.0;
#endif // _WIN32
}
<commit_msg>Changed field of view from 90 to 60 because 90 had some distortion.<commit_after>/**
 * @file Application.cpp
 *
 * @author Jan Dušek <xdusek17@stud.fit.vutbr.cz>
 * @date 2013
 */

#include "Application.h"

#include "Logging.h"
#include "Helpers.h"
#include "Common.h"
#include "Renderer.h"
#include "Scene.h"
#include "Node.h"
#include "ShaderManager.h"
#include "FpsCamera.h"
#include "Light.h"

#include "Cube.h"

#include <GL/glew.h>
#include <glm/gtc/matrix_transform.hpp>

#include <sstream>

const char* SDLApplication::DEFAULT_WND_TITLE = "Test app";

SDLApplication::SDLApplication(int argc, char** argv)
	: window(nullptr), context(nullptr), done(false), fps(60.0), windowTitle(DEFAULT_WND_TITLE),
	  renderer(new gl::Renderer())
{
	if (SDL_Init(SDL_INIT_VIDEO) != 0)
		throw SDLException("SDL_Init failed");

	createWindow(windowTitle, 800, 600);
}

SDLApplication::~SDLApplication() {
	SDL_GL_DeleteContext(context);
	SDL_DestroyWindow(window);
	SDL_Quit();
}

int SDLApplication::run() {
	init();

	uint64_t frameCount = 0;
	double prevTime = getTime();
	while (!done) {
		calculateFps(fps, prevTime, frameCount);
		processEvents();
		update();
		draw();
	}

	return 0;
}

void SDLApplication::setWindowTitle(const char* title) {
	if (title == nullptr)
		windowTitle = DEFAULT_WND_TITLE;
	else
		windowTitle = title;

	SDL_SetWindowTitle(window, windowTitle);
}

void SDLApplication::createWindow(const char* windowCaption, size_t width, size_t height) {
	this->width = width;
	this->height = height;

	// Set double buffering
	SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);

	// Create window
	window = SDL_CreateWindow(windowCaption, SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED,
		width, height, SDL_WINDOW_OPENGL);
	if (window == nullptr)
		throw SDLException("SDL_CreateWindow failed");

	context = SDL_GL_CreateContext(window);

	LOG(INFO) << "OpenGL version: " << glGetString(GL_VERSION);

	// Init GLEW
	GLenum err;
	glewExperimental = GL_TRUE;
	if ((err = glewInit()) != GLEW_OK)
		throw Exception((const char*)glewGetErrorString(err));

	LOG(INFO) << "Using GLEW " << glewGetString(GLEW_VERSION);

	// GL_EXT_direct_state_access detection broken in glew on my amd radeon 6630m
	// TODO: check if desired functions are not null manually
	/*if (!GLEW_EXT_direct_state_access)
		throw Exception("Missing EXT_direct_state_access extension!");*/

	grabMouse(true);
}

void SDLApplication::init() {
	renderer->setViewport(Viewport(static_cast<float>(width), static_cast<float>(height)));

	scene = std::unique_ptr<Scene>(new Scene(renderer.get()));

	auto material = std::make_shared<PhongMaterial>(renderer.get());
	ShaderManager shaderManager;
	material->setShader(shaderManager.getGlslProgram("phong"));

	PhongMaterialData materialData = { glm::vec4(0.0f, 0.1f, 0.0f, 1.0f),
		glm::vec4(0.8f, 0.3f, 0.1f, 1.0f), glm::vec4(0.3f, 0.3f, 0.3f, 1.0f), 5.0f };

	material->properties()->setData(materialData);
	material->properties()->flushData();

	auto mesh = std::make_shared<Mesh>();
	mesh->setPrimitiveType(PrimitiveType::TriangleList);

	std::vector<char> vertices(reinterpret_cast<const char*>(cubeVertices),
		reinterpret_cast<const char*>(cubeVertices) + sizeof(cubeVertices));
	std::vector<VertexElement> layout = create_vector<VertexElement>
		(VertexElement(3, VertexElementType::Float))(VertexElement(3, VertexElementType::Float));
	mesh->loadVertices(vertices, cubeVerticesCount, layout);

	std::vector<uint32_t> indices(reinterpret_cast<const unsigned*>(cubeIndices),
		reinterpret_cast<const unsigned*>(cubeIndices) + cubeIndicesCount);
	mesh->loadIndices(indices);

	scene->addNode(std::unique_ptr<Node>(new Node(mesh, material)));

	camera = std::unique_ptr<FpsCamera>(new FpsCamera(renderer.get()));
	camera->setProjectionMatrix(glm::perspective(60.0f, (float)width / height, 0.01f, 100.0f));
	camera->setPosition(-3.0f, 0.0f, 0.5f);
	camera->setMovementSpeed(2.0f);

	renderer->setCamera(camera.get());

	light = std::unique_ptr<Light>(new Light(renderer.get()));
	light->setPosition(glm::vec4(-1.0f, 0.0f, 5.0f, 1.0f));
	light->setAmbient(glm::vec4(1.0f, 1.0f, 1.0f, 1.0f));
	light->setDiffuse(glm::vec4(1.0f, 1.0f, 1.0f, 1.0f));
	light->setSpecular(glm::vec4(1.0f, 1.0f, 1.0f, 1.0f));
	light->flushChanges();

	renderer->setLight(light.get());
}

void SDLApplication::update() {
	std::ostringstream ss;
	ss << windowTitle << " - " << fps;
	SDL_SetWindowTitle(window, ss.str().c_str());

	handleKeyboard();

	camera->update();
}

void SDLApplication::draw() {

	renderer->drawFrame();

	SDL_GL_SwapWindow(window);
}

void SDLApplication::processEvents() {
	SDL_Event event;
	while(SDL_PollEvent(&event)) {
		switch (event.type)
		{
		case SDL_QUIT:
			done = true;
			break;

		case SDL_KEYUP:
		case SDL_KEYDOWN:
			keyboardHandler.handleEvent(event.key);
			break;

		case SDL_MOUSEMOTION:
			handleMouseMove(event.motion.xrel, event.motion.yrel);
			break;
		}
	}
}

void SDLApplication::handleKeyboard() {
	if (keyboardHandler.isPressed(SDLK_ESCAPE)) {
		SDL_Event quitEvent = { SDL_QUIT };
		SDL_PushEvent(&quitEvent);
		return;
	}

	if (keyboardHandler.isPressed(SDLK_LALT)) {
		grabMouse(!mouseGrabbed);
	}

	if (keyboardHandler.isPressed(SDLK_w))
		camera->goForward(fps);
	if (keyboardHandler.isPressed(SDLK_s))
		camera->goBackward(fps);
	if (keyboardHandler.isPressed(SDLK_a))
		camera->goLeft(fps);
	if (keyboardHandler.isPressed(SDLK_d))
		camera->goRight(fps);
}

void SDLApplication::handleMouseMove(int xrel, int yrel) {
	/*int winWidth, winHeight;
	SDL_GetWindowSize(window, &winWidth, &winHeight);*/

	camera->yaw(static_cast<float>(xrel));
	camera->pitch(static_cast<float>(yrel));
}

void SDLApplication::grabMouse(bool flag) {
	if (SDL_SetRelativeMouseMode(flag ? SDL_TRUE : SDL_FALSE) == -1) {
		LOG(ERROR) << "SDL_SetRelativeMouseMode failed: " << SDL_GetError();
		mouseGrabbed = false;
		return;
	}
	mouseGrabbed = flag;
}

void SDLApplication::calculateFps(float& fps, double& prevTime, uint64_t& frameCount) {
	frameCount++;

	double currentTime = getTime();
	double timeInterval = currentTime - prevTime;
	if (timeInterval > 1.0) {
		fps = static_cast<float>(frameCount / timeInterval);
		prevTime = currentTime;
		frameCount = 0;
	}
}

double SDLApplication::getTime() {
#ifdef _WIN32
	// windows version
	static LARGE_INTEGER freq;
	static bool first = true;
	if (first) {
		first = false;
		if (!QueryPerformanceFrequency(&freq))
			throw Win32Exception("QueryPerformanceFrequency failed!");
	}

	LARGE_INTEGER val;
	QueryPerformanceCounter(&val);
	return static_cast<double>(val.QuadPart) / static_cast<double>(freq.QuadPart);
#else
	// posix version
	struct timeval tv;
	if (gettimeofday(&tv, NULL) == -1)
		throw SystemException("gettimeofday failed!");

	return static_cast<double>(tv.tv_sec) + static_cast<double>(tv.tv_usec) / 1000000.0;
#endif // _WIN32
}
<|endoftext|>


<commit_before>#pragma once

/// \addtogroup Client
/// \{

/// \def ZKPP_USER_CONFIG
/// A user-defined configuration file to be included before all other ZooKeeper C++ content.
#ifdef ZKPP_USER_CONFIG
#   include ZKPP_USER_CONFIG
#endif

#define ZKPP_VERSION_MAJOR 0
#define ZKPP_VERSION_MINOR 2
#define ZKPP_VERSION_PATCH 1

/// \def ZKPP_DEBUG
/// Was ZooKeeper C++ compiled in debug mode? This value must be the same between when the SO was built and when you are
/// compiling. In general, this is not useful outside of library maintainers.
///
/// \warning
/// Keep in mind this value is \e always defined. Use `#if ZKPP_DEBUG`, \e not `#ifdef ZKPP_DEBUG`.
#ifndef ZKPP_DEBUG
#   define ZKPP_DEBUG 0
#endif

/// \}

namespace zk
{

/// \addtogroup Client
/// \{

/// A simple, unowned pointer. It operates exactly like using \c *, but removes the question of \c * associativity and
/// is easier to read when \c const qualifiers are involved.
template <typename T>
using ptr = T*;

/// \}

}
<commit_msg>build: Update master version to 0.2.2.<commit_after>#pragma once

/// \addtogroup Client
/// \{

/// \def ZKPP_USER_CONFIG
/// A user-defined configuration file to be included before all other ZooKeeper C++ content.
#ifdef ZKPP_USER_CONFIG
#   include ZKPP_USER_CONFIG
#endif

#define ZKPP_VERSION_MAJOR 0
#define ZKPP_VERSION_MINOR 2
#define ZKPP_VERSION_PATCH 2

/// \def ZKPP_DEBUG
/// Was ZooKeeper C++ compiled in debug mode? This value must be the same between when the SO was built and when you are
/// compiling. In general, this is not useful outside of library maintainers.
///
/// \warning
/// Keep in mind this value is \e always defined. Use `#if ZKPP_DEBUG`, \e not `#ifdef ZKPP_DEBUG`.
#ifndef ZKPP_DEBUG
#   define ZKPP_DEBUG 0
#endif

/// \}

namespace zk
{

/// \addtogroup Client
/// \{

/// A simple, unowned pointer. It operates exactly like using \c *, but removes the question of \c * associativity and
/// is easier to read when \c const qualifiers are involved.
template <typename T>
using ptr = T*;

/// \}

}
<|endoftext|>