<commit_before>/* Copyright 2014-present Facebook, Inc.
 * Licensed under the Apache License, Version 2.0 */

#include "watchman.h"
#include "InMemoryView.h"
#include "watchman_synchronized.h"

#include <algorithm>
#include <condition_variable>
#include <list>
#include <iterator>
#include <tuple>
#include <mutex>

#ifdef _WIN32

#define NETWORK_BUF_SIZE (64*1024)

namespace {

struct Item {
  w_string path;
  int flags;

  Item(w_string &&path, int flags) : path(std::move(path)), flags(flags) {}
};

}

struct WinWatcher : public Watcher {
  HANDLE ping{INVALID_HANDLE_VALUE}, olapEvent{INVALID_HANDLE_VALUE};
  HANDLE dir_handle{INVALID_HANDLE_VALUE};

  std::condition_variable cond;
  watchman::Synchronized<std::list<Item>, std::mutex> changedItems;

  explicit WinWatcher(w_root_t* root);
  ~WinWatcher();

  std::unique_ptr<watchman_dir_handle> startWatchDir(
      const std::shared_ptr<w_root_t>& root,
      struct watchman_dir* dir,
      const char* path) override;

  bool consumeNotify(
      const std::shared_ptr<w_root_t>& root,
      PendingCollection::LockedPtr& coll) override;

  bool waitNotify(int timeoutms) override;
  bool start(const std::shared_ptr<w_root_t>& root) override;
  void signalThreads() override;
  void readChangesThread(const std::shared_ptr<w_root_t>& root);
};

WinWatcher::WinWatcher(w_root_t* root)
    : Watcher("win32", WATCHER_HAS_PER_FILE_NOTIFICATIONS) {
  int err;

  auto wpath = root->root_path.piece().asWideUNC();

  // Create an overlapped handle so that we can avoid blocking forever
  // in ReadDirectoryChangesW
  dir_handle = CreateFileW(
      wpath.c_str(),
      GENERIC_READ,
      FILE_SHARE_READ | FILE_SHARE_DELETE | FILE_SHARE_WRITE,
      nullptr,
      OPEN_EXISTING,
      FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OVERLAPPED,
      nullptr);
  if (!dir_handle) {
    throw std::runtime_error(
        std::string("failed to open dir ") + root->root_path.c_str() + ": " +
        win32_strerror(GetLastError()));
  }

  ping = CreateEvent(nullptr, TRUE, FALSE, nullptr);
  if (!ping) {
    throw std::runtime_error(
        std::string("failed to create event: ") +
        win32_strerror(GetLastError()));
  }
  olapEvent = CreateEvent(nullptr, TRUE, FALSE, nullptr);
  if (!olapEvent) {
    throw std::runtime_error(
        std::string("failed to create event: ") +
        win32_strerror(GetLastError()));
  }
}

WinWatcher::~WinWatcher() {
  if (ping != INVALID_HANDLE_VALUE) {
    CloseHandle(ping);
  }
  if (olapEvent != INVALID_HANDLE_VALUE) {
    CloseHandle(olapEvent);
  }
  if (dir_handle != INVALID_HANDLE_VALUE) {
    CloseHandle(dir_handle);
  }
}

void WinWatcher::signalThreads() {
  SetEvent(ping);
}

void WinWatcher::readChangesThread(const std::shared_ptr<w_root_t>& root) {
  std::vector<uint8_t> buf;
  DWORD err, filter;
  auto olap = OVERLAPPED();
  BOOL initiate_read = true;
  HANDLE handles[2] = {olapEvent, ping};
  DWORD bytes;

  w_set_thread_name("readchange %s", root->root_path.c_str());
  watchman::log(watchman::DBG, "initializing\n");

  // Artificial extra latency to impose around processing changes.
  // This is needed to avoid trying to access files and dirs too
  // soon after a change is noticed, as this can cause recursive
  // deletes to fail.
  auto extraLatency = root->config.getInt("win32_batch_latency_ms", 30);

  DWORD size = root->config.getInt("win32_rdcw_buf_size", 16384);

  // Block until winmatch_root_st is waiting for our initialization
  {
    auto wlock = changedItems.wlock();

    filter = FILE_NOTIFY_CHANGE_FILE_NAME | FILE_NOTIFY_CHANGE_DIR_NAME |
        FILE_NOTIFY_CHANGE_ATTRIBUTES | FILE_NOTIFY_CHANGE_SIZE |
        FILE_NOTIFY_CHANGE_LAST_WRITE;

    olap.hEvent = olapEvent;

    buf.resize(size);

    if (!ReadDirectoryChangesW(
            dir_handle, &buf[0], size, TRUE, filter, nullptr, &olap, nullptr)) {
      err = GetLastError();
      w_log(
          W_LOG_ERR,
          "ReadDirectoryChangesW: failed, cancel watch. %s\n",
          win32_strerror(err));
      root->cancel();
      return;
    }
    // Signal that we are done with init.  We MUST do this AFTER our first
    // successful ReadDirectoryChangesW, otherwise there is a race condition
    // where we'll miss observing the cookie for a query that comes in
    // after we've crawled but before the watch is established.
    w_log(W_LOG_DBG, "ReadDirectoryChangesW signalling as init done\n");
    cond.notify_one();
  }
  initiate_read = false;

  std::list<Item> items;

  // The mutex must not be held when we enter the loop
  while (!root->inner.cancelled) {
    if (initiate_read) {
      if (!ReadDirectoryChangesW(
              dir_handle,
              &buf[0],
              size,
              TRUE,
              filter,
              nullptr,
              &olap,
              nullptr)) {
        err = GetLastError();
        w_log(W_LOG_ERR,
            "ReadDirectoryChangesW: failed, cancel watch. %s\n",
            win32_strerror(err));
        root->cancel();
        break;
      } else {
        initiate_read = false;
      }
    }

    watchman::log(watchman::DBG, "waiting for change notifications\n");
    DWORD status = WaitForMultipleObjects(
        2,
        handles,
        FALSE,
        // We use a 10 second timeout by default until we start accumulating a
        // batch.  Once we have a batch we prefer to add more to it than notify
        // immediately, so we introduce a 30ms latency.  Without this artificial
        // latency we'll wake up and start trying to look at a directory that
        // may be in the process of being recursively deleted and that act can
        // block the recursive delete.
        items.empty() ? 10000 : extraLatency);
    watchman::log(watchman::DBG, "wait returned with status ", status, "\n");

    if (status == WAIT_OBJECT_0) {
      bytes = 0;
      if (!GetOverlappedResult(dir_handle, &olap, &bytes, FALSE)) {
        err = GetLastError();
        w_log(
            W_LOG_ERR,
            "overlapped ReadDirectoryChangesW(%s): 0x%x %s\n",
            root->root_path.c_str(),
            err,
            win32_strerror(err));

        if (err == ERROR_INVALID_PARAMETER && size > NETWORK_BUF_SIZE) {
          // May be a network buffer related size issue; the docs say that
          // we can hit this when watching a UNC path. Let's downsize and
          // retry the read just one time
          w_log(
              W_LOG_ERR,
              "retrying watch for possible network location %s "
              "with smaller buffer\n",
              root->root_path.c_str());
          size = NETWORK_BUF_SIZE;
          initiate_read = true;
          continue;
        }

        if (err == ERROR_NOTIFY_ENUM_DIR) {
          root->scheduleRecrawl("ERROR_NOTIFY_ENUM_DIR");
        } else {
          w_log(
              W_LOG_ERR, "Cancelling watch for %s\n", root->root_path.c_str());
          root->cancel();
          break;
        }
      } else {
        PFILE_NOTIFY_INFORMATION not = (PFILE_NOTIFY_INFORMATION)buf.data();

        while (true) {
          DWORD n_chars;

          // FileNameLength is in BYTES, but FileName is WCHAR
          n_chars = not->FileNameLength / sizeof(not->FileName[0]);
          w_string name(not->FileName, n_chars);

          auto full = w_string::pathCat({root->root_path, name});

          if (!root->ignore.isIgnored(full.data(), full.size())) {
            // If we have a delete or rename-away it may be part of
            // a recursive tree remove or rename.  In that situation
            // the notifications that we'll receive from the OS will
            // be from the leaves and bubble up to the root of the
            // delete/rename.  We want to flag those paths for recursive
            // analysis so that we can prune children from the trie
            // that is built when we pass this to the pending list
            // later.  We don't do that here in this thread because
            // we're trying to minimize latency in this context.
            items.emplace_back(
                std::move(full),
                (not->Action &
                 (FILE_ACTION_REMOVED | FILE_ACTION_RENAMED_OLD_NAME)) != 0
                    ? W_PENDING_RECURSIVE
                    : 0);
          }

          // Advance to next item
          if (not->NextEntryOffset == 0) {
            break;
          }
          not = (PFILE_NOTIFY_INFORMATION)(not->NextEntryOffset + (char*)not);
        }

        ResetEvent(olapEvent);
        initiate_read = true;
      }
    } else if (status == WAIT_OBJECT_0 + 1) {
      w_log(W_LOG_ERR, "signalled\n");
      break;
    } else if (status == WAIT_TIMEOUT) {
      if (!items.empty()) {
        watchman::log(watchman::DBG,
                      "timed out waiting for changes, and we have ",
                      items.size(), " items; move and notify\n");
        auto wlock = changedItems.wlock();
        wlock->splice(wlock->end(), items);
        cond.notify_one();
      }
    } else {
      w_log(W_LOG_ERR, "impossible wait status=%d\n", status);
      break;
    }
  }

  w_log(W_LOG_DBG, "done\n");
}

bool WinWatcher::start(const std::shared_ptr<w_root_t>& root) {
  int err;

  // Spin up the changes reading thread; it owns a ref on the root

  try {
    // Acquire the mutex so thread initialization waits until we release it
    auto wlock = changedItems.wlock();

    watchman::log(watchman::DBG, "starting readChangesThread\n");
    auto self = std::dynamic_pointer_cast<WinWatcher>(shared_from_this());
    std::thread thread([ self, root ]() noexcept {
      try {
        self->readChangesThread(root);
      } catch (const std::exception& e) {
        watchman::log(watchman::ERR, "uncaught exception: ", e.what());
        root->cancel();
      }

      // Ensure that we signal the condition variable before we
      // finish this thread.  That ensures that don't get stuck
      // waiting in WinWatcher::start if something unexpected happens.
      auto wlock = self->changedItems.wlock();
      self->cond.notify_one();
    });
    // We have to detach because the readChangesThread may wind up
    // being the last thread to reference the watcher state and
    // cannot join itself.
    thread.detach();

    // Allow thread init to proceed; wait for its signal
    if (cond.wait_for(wlock.getUniqueLock(), std::chrono::seconds(10)) ==
        std::cv_status::timeout) {
      watchman::log(
          watchman::ERR, "timedout waiting for readChangesThread to start\n");
      root->cancel();
      return false;
    }

    if (root->failure_reason) {
      w_log(
          W_LOG_ERR,
          "failed to start readchanges thread: %s\n",
          root->failure_reason.c_str());
      return false;
    }
    return true;
  } catch (const std::exception& e) {
    w_log(W_LOG_ERR, "failed to start readchanges thread: %s\n", e.what());
    return false;
  }
}

std::unique_ptr<watchman_dir_handle> WinWatcher::startWatchDir(
    const std::shared_ptr<w_root_t>& root,
    struct watchman_dir* dir,
    const char* path) {
  return w_dir_open(path);
}

bool WinWatcher::consumeNotify(
    const std::shared_ptr<w_root_t>& root,
    PendingCollection::LockedPtr& coll) {
  std::list<Item> items;
  struct timeval now;

  {
    auto wlock = changedItems.wlock();
    std::swap(items, *wlock);
  }

  gettimeofday(&now, nullptr);

  for (auto& item : items) {
    watchman::log(watchman::DBG, "readchanges: add pending ", item.path, " ",
                  item.flags, "\n");
    coll->add(item.path, now, W_PENDING_VIA_NOTIFY | item.flags);
  }

  return !items.empty();
}

bool WinWatcher::waitNotify(int timeoutms) {
  auto wlock = changedItems.wlock();
  cond.wait_for(wlock.getUniqueLock(), std::chrono::milliseconds(timeoutms));
  return !wlock->empty();
}

static RegisterWatcher<WinWatcher> reg("win32");

#endif // _WIN32

/* vim:ts=2:sw=2:et:
 */
<commit_msg>fix compilation of watcher/win32.cpp on vs 2017<commit_after>/* Copyright 2014-present Facebook, Inc.
 * Licensed under the Apache License, Version 2.0 */

#include "watchman.h"
#include "InMemoryView.h"
#include "watchman_synchronized.h"

#include <algorithm>
#include <condition_variable>
#include <list>
#include <iterator>
#include <tuple>
#include <mutex>

#ifdef _WIN32

#define NETWORK_BUF_SIZE (64*1024)

namespace {

struct Item {
  w_string path;
  int flags;

  Item(w_string &&path, int flags) : path(std::move(path)), flags(flags) {}
};

}

struct WinWatcher : public Watcher {
  HANDLE ping{INVALID_HANDLE_VALUE}, olapEvent{INVALID_HANDLE_VALUE};
  HANDLE dir_handle{INVALID_HANDLE_VALUE};

  std::condition_variable cond;
  watchman::Synchronized<std::list<Item>, std::mutex> changedItems;

  explicit WinWatcher(w_root_t* root);
  ~WinWatcher();

  std::unique_ptr<watchman_dir_handle> startWatchDir(
      const std::shared_ptr<w_root_t>& root,
      struct watchman_dir* dir,
      const char* path) override;

  bool consumeNotify(
      const std::shared_ptr<w_root_t>& root,
      PendingCollection::LockedPtr& coll) override;

  bool waitNotify(int timeoutms) override;
  bool start(const std::shared_ptr<w_root_t>& root) override;
  void signalThreads() override;
  void readChangesThread(const std::shared_ptr<w_root_t>& root);
};

WinWatcher::WinWatcher(w_root_t* root)
    : Watcher("win32", WATCHER_HAS_PER_FILE_NOTIFICATIONS) {
  int err;

  auto wpath = root->root_path.piece().asWideUNC();

  // Create an overlapped handle so that we can avoid blocking forever
  // in ReadDirectoryChangesW
  dir_handle = CreateFileW(
      wpath.c_str(),
      GENERIC_READ,
      FILE_SHARE_READ | FILE_SHARE_DELETE | FILE_SHARE_WRITE,
      nullptr,
      OPEN_EXISTING,
      FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OVERLAPPED,
      nullptr);
  if (!dir_handle) {
    throw std::runtime_error(
        std::string("failed to open dir ") + root->root_path.c_str() + ": " +
        win32_strerror(GetLastError()));
  }

  ping = CreateEvent(nullptr, TRUE, FALSE, nullptr);
  if (!ping) {
    throw std::runtime_error(
        std::string("failed to create event: ") +
        win32_strerror(GetLastError()));
  }
  olapEvent = CreateEvent(nullptr, TRUE, FALSE, nullptr);
  if (!olapEvent) {
    throw std::runtime_error(
        std::string("failed to create event: ") +
        win32_strerror(GetLastError()));
  }
}

WinWatcher::~WinWatcher() {
  if (ping != INVALID_HANDLE_VALUE) {
    CloseHandle(ping);
  }
  if (olapEvent != INVALID_HANDLE_VALUE) {
    CloseHandle(olapEvent);
  }
  if (dir_handle != INVALID_HANDLE_VALUE) {
    CloseHandle(dir_handle);
  }
}

void WinWatcher::signalThreads() {
  SetEvent(ping);
}

void WinWatcher::readChangesThread(const std::shared_ptr<w_root_t>& root) {
  std::vector<uint8_t> buf;
  DWORD err, filter;
  auto olap = OVERLAPPED();
  BOOL initiate_read = true;
  HANDLE handles[2] = {olapEvent, ping};
  DWORD bytes;

  w_set_thread_name("readchange %s", root->root_path.c_str());
  watchman::log(watchman::DBG, "initializing\n");

  // Artificial extra latency to impose around processing changes.
  // This is needed to avoid trying to access files and dirs too
  // soon after a change is noticed, as this can cause recursive
  // deletes to fail.
  auto extraLatency = root->config.getInt("win32_batch_latency_ms", 30);

  DWORD size = root->config.getInt("win32_rdcw_buf_size", 16384);

  // Block until winmatch_root_st is waiting for our initialization
  {
    auto wlock = changedItems.wlock();

    filter = FILE_NOTIFY_CHANGE_FILE_NAME | FILE_NOTIFY_CHANGE_DIR_NAME |
        FILE_NOTIFY_CHANGE_ATTRIBUTES | FILE_NOTIFY_CHANGE_SIZE |
        FILE_NOTIFY_CHANGE_LAST_WRITE;

    olap.hEvent = olapEvent;

    buf.resize(size);

    if (!ReadDirectoryChangesW(
            dir_handle, &buf[0], size, TRUE, filter, nullptr, &olap, nullptr)) {
      err = GetLastError();
      w_log(
          W_LOG_ERR,
          "ReadDirectoryChangesW: failed, cancel watch. %s\n",
          win32_strerror(err));
      root->cancel();
      return;
    }
    // Signal that we are done with init.  We MUST do this AFTER our first
    // successful ReadDirectoryChangesW, otherwise there is a race condition
    // where we'll miss observing the cookie for a query that comes in
    // after we've crawled but before the watch is established.
    w_log(W_LOG_DBG, "ReadDirectoryChangesW signalling as init done\n");
    cond.notify_one();
  }
  initiate_read = false;

  std::list<Item> items;

  // The mutex must not be held when we enter the loop
  while (!root->inner.cancelled) {
    if (initiate_read) {
      if (!ReadDirectoryChangesW(
              dir_handle,
              &buf[0],
              size,
              TRUE,
              filter,
              nullptr,
              &olap,
              nullptr)) {
        err = GetLastError();
        w_log(W_LOG_ERR,
            "ReadDirectoryChangesW: failed, cancel watch. %s\n",
            win32_strerror(err));
        root->cancel();
        break;
      } else {
        initiate_read = false;
      }
    }

    watchman::log(watchman::DBG, "waiting for change notifications\n");
    DWORD status = WaitForMultipleObjects(
        2,
        handles,
        FALSE,
        // We use a 10 second timeout by default until we start accumulating a
        // batch.  Once we have a batch we prefer to add more to it than notify
        // immediately, so we introduce a 30ms latency.  Without this artificial
        // latency we'll wake up and start trying to look at a directory that
        // may be in the process of being recursively deleted and that act can
        // block the recursive delete.
        items.empty() ? 10000 : extraLatency);
    watchman::log(watchman::DBG, "wait returned with status ", status, "\n");

    if (status == WAIT_OBJECT_0) {
      bytes = 0;
      if (!GetOverlappedResult(dir_handle, &olap, &bytes, FALSE)) {
        err = GetLastError();
        w_log(
            W_LOG_ERR,
            "overlapped ReadDirectoryChangesW(%s): 0x%x %s\n",
            root->root_path.c_str(),
            err,
            win32_strerror(err));

        if (err == ERROR_INVALID_PARAMETER && size > NETWORK_BUF_SIZE) {
          // May be a network buffer related size issue; the docs say that
          // we can hit this when watching a UNC path. Let's downsize and
          // retry the read just one time
          w_log(
              W_LOG_ERR,
              "retrying watch for possible network location %s "
              "with smaller buffer\n",
              root->root_path.c_str());
          size = NETWORK_BUF_SIZE;
          initiate_read = true;
          continue;
        }

        if (err == ERROR_NOTIFY_ENUM_DIR) {
          root->scheduleRecrawl("ERROR_NOTIFY_ENUM_DIR");
        } else {
          w_log(
              W_LOG_ERR, "Cancelling watch for %s\n", root->root_path.c_str());
          root->cancel();
          break;
        }
      } else {
        PFILE_NOTIFY_INFORMATION notify = (PFILE_NOTIFY_INFORMATION)buf.data();

        while (true) {
          DWORD n_chars;

          // FileNameLength is in BYTES, but FileName is WCHAR
          n_chars = notify->FileNameLength / sizeof(notify->FileName[0]);
          w_string name(notify->FileName, n_chars);

          auto full = w_string::pathCat({root->root_path, name});

          if (!root->ignore.isIgnored(full.data(), full.size())) {
            // If we have a delete or rename-away it may be part of
            // a recursive tree remove or rename.  In that situation
            // the notifications that we'll receive from the OS will
            // be from the leaves and bubble up to the root of the
            // delete/rename.  We want to flag those paths for recursive
            // analysis so that we can prune children from the trie
            // that is built when we pass this to the pending list
            // later.  We don't do that here in this thread because
            // we're trying to minimize latency in this context.
            items.emplace_back(
                std::move(full),
                (notify->Action &
                 (FILE_ACTION_REMOVED | FILE_ACTION_RENAMED_OLD_NAME)) != 0
                    ? W_PENDING_RECURSIVE
                    : 0);
          }

          // Advance to next item
          if (notify->NextEntryOffset == 0) {
            break;
          }
          notify = (PFILE_NOTIFY_INFORMATION)(
              notify->NextEntryOffset + (char*)notify);
        }

        ResetEvent(olapEvent);
        initiate_read = true;
      }
    } else if (status == WAIT_OBJECT_0 + 1) {
      w_log(W_LOG_ERR, "signalled\n");
      break;
    } else if (status == WAIT_TIMEOUT) {
      if (!items.empty()) {
        watchman::log(watchman::DBG,
                      "timed out waiting for changes, and we have ",
                      items.size(), " items; move and notify\n");
        auto wlock = changedItems.wlock();
        wlock->splice(wlock->end(), items);
        cond.notify_one();
      }
    } else {
      w_log(W_LOG_ERR, "impossible wait status=%d\n", status);
      break;
    }
  }

  w_log(W_LOG_DBG, "done\n");
}

bool WinWatcher::start(const std::shared_ptr<w_root_t>& root) {
  int err;

  // Spin up the changes reading thread; it owns a ref on the root

  try {
    // Acquire the mutex so thread initialization waits until we release it
    auto wlock = changedItems.wlock();

    watchman::log(watchman::DBG, "starting readChangesThread\n");
    auto self = std::dynamic_pointer_cast<WinWatcher>(shared_from_this());
    std::thread thread([ self, root ]() noexcept {
      try {
        self->readChangesThread(root);
      } catch (const std::exception& e) {
        watchman::log(watchman::ERR, "uncaught exception: ", e.what());
        root->cancel();
      }

      // Ensure that we signal the condition variable before we
      // finish this thread.  That ensures that don't get stuck
      // waiting in WinWatcher::start if something unexpected happens.
      auto wlock = self->changedItems.wlock();
      self->cond.notify_one();
    });
    // We have to detach because the readChangesThread may wind up
    // being the last thread to reference the watcher state and
    // cannot join itself.
    thread.detach();

    // Allow thread init to proceed; wait for its signal
    if (cond.wait_for(wlock.getUniqueLock(), std::chrono::seconds(10)) ==
        std::cv_status::timeout) {
      watchman::log(
          watchman::ERR, "timedout waiting for readChangesThread to start\n");
      root->cancel();
      return false;
    }

    if (root->failure_reason) {
      w_log(
          W_LOG_ERR,
          "failed to start readchanges thread: %s\n",
          root->failure_reason.c_str());
      return false;
    }
    return true;
  } catch (const std::exception& e) {
    w_log(W_LOG_ERR, "failed to start readchanges thread: %s\n", e.what());
    return false;
  }
}

std::unique_ptr<watchman_dir_handle> WinWatcher::startWatchDir(
    const std::shared_ptr<w_root_t>& root,
    struct watchman_dir* dir,
    const char* path) {
  return w_dir_open(path);
}

bool WinWatcher::consumeNotify(
    const std::shared_ptr<w_root_t>& root,
    PendingCollection::LockedPtr& coll) {
  std::list<Item> items;
  struct timeval now;

  {
    auto wlock = changedItems.wlock();
    std::swap(items, *wlock);
  }

  gettimeofday(&now, nullptr);

  for (auto& item : items) {
    watchman::log(watchman::DBG, "readchanges: add pending ", item.path, " ",
                  item.flags, "\n");
    coll->add(item.path, now, W_PENDING_VIA_NOTIFY | item.flags);
  }

  return !items.empty();
}

bool WinWatcher::waitNotify(int timeoutms) {
  auto wlock = changedItems.wlock();
  cond.wait_for(wlock.getUniqueLock(), std::chrono::milliseconds(timeoutms));
  return !wlock->empty();
}

static RegisterWatcher<WinWatcher> reg("win32");

#endif // _WIN32

/* vim:ts=2:sw=2:et:
 */
<|endoftext|>


<commit_before>#include "convert.h"
#include <cstring>
namespace converter {
	cv::Mat BITMAP_to_cv_Mat(const BITMAP & img) {
		cv::Mat re;
		cv::flip(cv::Mat(img.bmWidth, img.bmHeight, CV_8UC4, img.bmBits), re, 0);//上下反転
		return re;
	}
}
<commit_msg>fix Mat construction by using user-allocated data<commit_after>#include "convert.h"
#include <cstring>
namespace converter {
	cv::Mat BITMAP_to_cv_Mat(const BITMAP & img) {
		cv::Mat re(img.bmHeight, img.bmWidth, CV_8UC4, img.bmBits,img.bmWidthBytes);
		cv::flip(re, re, 0);//上下反転
		return re;
	}
}
<|endoftext|>


<commit_before>#include <stdio.h>
#include <opencv2/opencv.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <wiringPi.h>
#include "camera.hpp"
#include "../motor.h"

#pragma comment(lib,"opencv_world320.lib")

static const int ROTATE_POWER = 20;
static const int ROTATE_MILLISECONDS = 200;
static const int LEFT_MAX = -100;
static const int RIGHT_MAX = 100;
static const int CENTER_THRESHOLD = 30;//-30~30で直進するようにする
int main(void)
{
	cv::Mat red = Mred(takePhoto());
	countArea(red);
	pwm_initialize();
while(1)
{
	if(LEFT_MAX<getCenter(red)<-CENTER_THRESHOLD)
	{
		motor_right(ROTATE_POWER);
		delay(ROTATE_MILLISECONDS);
	}
	if(CENTER_THRESHOLD<getCenter(red)<RIGHT_MAX)
	{
		motor_left(ROTATE_POWER);
		delay(ROTATE_MILLISECONDS);
	}
	if(-CENTER_THRESHOLD<getCenter(red)<30)
	{
		motor_forward(100);
		delay(200);
	}
 }
return 0;
}
<commit_msg>debug<commit_after>#include <stdio.h>
#include <opencv2/opencv.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <wiringPi.h>
#include "camera.hpp"
#include "../motor.h"

#pragma comment(lib,"opencv_world320.lib")

static const int ROTATE_POWER = 20;
static const int ROTATE_MILLISECONDS = 200;
static const int LEFT_MAX = -100;
static const int RIGHT_MAX = 100;
static const int CENTER_THRESHOLD = 30;//-30~30で直進するようにする
int main(void)
{
	pwm_initialize();
while(1)
{
	cv::Mat red = Mred(takePhoto());
	countArea(red);
	int center = getCenter(red)
	if(LEFT_MAX<center<-CENTER_THRESHOLD)
	{
		motor_right(ROTATE_POWER);
		delay(ROTATE_MILLISECONDS);
	}
	if(CENTER_THRESHOLD<center<RIGHT_MAX)
	{
		motor_left(ROTATE_POWER);
		delay(ROTATE_MILLISECONDS);
	}
	if(-CENTER_THRESHOLD<center<CENTER_THRESHOLD)
	{
		printf("hoge\n");
		motor_forward(100);
		delay(200);
	}
 }
return 0;
}
<|endoftext|>


<commit_before>#include <stdio.h>
#include <signal.h>
#include <stdlib.h>
#include <opencv2/opencv.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <time.h>
#include <wiringPi.h>
#include "camera.hpp"
#include "../motor.h"

#pragma comment(lib,"opencv_world320.lib")

static const int ROTATE_POWER = 100;
static const int ROTATE_MILLISECONDS = 200;
static const int LEFT_MAX = -100;
static const int RIGHT_MAX = 100;
static const int CENTER_THRESHOLD = 30;//-30~30で直進するようにする
static const double EXIST_THRESHOLD = 0.1;//ゴール存在判定 パーセンテージ
static const int TIME_LIMIT = 900;//10分
static const int DELAY_TIME = 1300;

void handler(int signum)
{
	motor_stop();
	delay(100);
	exit(1);
}

int main (void)
{
	signal(SIGINT, handler);
	time_t startTime;
	time(&startTime);
	time_t lastTime;
	time(&lastTime);
	pwm_initialize();
	Camera camera;
	while(lastTime-startTime<TIME_LIMIT)
	{
		printf("lastTime - startTime %d\n",lastTime - startTime);
		time(&lastTime);
		camera.takePhoto();
	  camera.binarize();
	  double count = camera.countArea();
		if(count < EXIST_THRESHOLD)
		{
			//回転するだけ
			motor_right(ROTATE_POWER);
			delay(ROTATE_MILLISECONDS);
			motor_stop();
			delay(DELAY_TIME);
		}
		else
		{
			//見つけれたら前進
			motor_forward(100);
			delay(400);
			motor_stop();
			delay(DELAY_TIME);
		}
	}
	printf("TIME IS OUT\n");
	return 0;
}
<commit_msg>debug<commit_after>#include <stdio.h>
#include <signal.h>
#include <stdlib.h>
#include <opencv2/opencv.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <time.h>
#include <wiringPi.h>
#include "camera.hpp"
#include "../motor.h"

#pragma comment(lib,"opencv_world320.lib")

static const int ROTATE_POWER = 100;
static const int ROTATE_MILLISECONDS = 200;
static const int LEFT_MAX = -100;
static const int RIGHT_MAX = 100;
static const int CENTER_THRESHOLD = 30;//-30~30で直進するようにする
static const double EXIST_THRESHOLD = 0.1;//ゴール存在判定 パーセンテージ
static const int TIME_LIMIT = 900;//10分
static const int DELAY_TIME = 2000;

void handler(int signum)
{
	motor_stop();
	delay(100);
	exit(1);
}

int main (void)
{
	signal(SIGINT, handler);
	time_t startTime;
	time(&startTime);
	time_t lastTime;
	time(&lastTime);
	pwm_initialize();
	Camera camera;
	while(lastTime-startTime<TIME_LIMIT)
	{
		printf("lastTime - startTime %d\n",lastTime - startTime);
		time(&lastTime);
		camera.takePhoto();
	  camera.binarize();
	  double count = camera.countArea();
		if(count < EXIST_THRESHOLD)
		{
			//回転するだけ
			motor_right(ROTATE_POWER);
			delay(ROTATE_MILLISECONDS);
			motor_stop();
			delay(DELAY_TIME);
		}
		else
		{
			//見つけれたら前進
			motor_forward(100);
			delay(400);
			motor_stop();
			delay(DELAY_TIME);
		}
	}
	printf("TIME IS OUT\n");
	return 0;
}
<|endoftext|>


<commit_before>/******************************************************************************\
* File:          test.cpp
* Purpose:       Implementation for wxextension cpp unit testing
* Author:        Anton van Wezenbeek
* RCS-ID:        $Id$
* Created:       za 17 jan 2009 11:51:20 CET
*
* Copyright (c) 2009 Anton van Wezenbeek
* All rights are reserved. Reproduction in whole or part is prohibited
* without the written consent of the copyright owner.
\******************************************************************************/

#include <TestCaller.h>
#include "test.h"

#define TEST_FILE "./test.h"
#define TEST_BIN "./test.bin"

void wxExTestFixture::setUp()
{
  m_Config = new wxExConfig("test.cfg", wxCONFIG_USE_LOCAL_FILE);
  m_File = new wxExFile(TEST_FILE);
  m_FileName = new wxExFileName(TEST_FILE);
  m_FileNameStatistics = new wxExFileNameStatistics(TEST_FILE);
  m_Lexer = new wxExLexer();
  m_Lexers = new wxExLexers(wxFileName("../extension/data/lexers.xml"));
  m_RCS = new wxExRCS();
  m_Stat = new wxExStat(TEST_FILE);
  m_Statistics = new wxExStatistics<long>();
}

void wxExTestFixture::testConstructors()
{
  CPPUNIT_ASSERT(m_File != NULL);
}

void wxExTestFixture::testMethods()
{
  // test wxExConfig
  CPPUNIT_ASSERT(m_Config->Get("keystring", "val") == "val");
  CPPUNIT_ASSERT(m_Config->Get("keylong", 12) == 12);
  CPPUNIT_ASSERT(m_Config->GetBool("keybool", true));
  CPPUNIT_ASSERT(m_Config->GetFindReplaceData() != NULL);
  m_Config->Set("keystring", "val2");
  CPPUNIT_ASSERT(m_Config->Get("keystring", "val") == "val2");
  m_Config->Set("keylong", 15);
  CPPUNIT_ASSERT(m_Config->Get("keylong", 7) == 15);
  m_Config->Set("keybool", false);
  CPPUNIT_ASSERT(m_Config->GetBool("keybool", true) == false);
  m_Config->Toggle("keybool");
  CPPUNIT_ASSERT(m_Config->GetBool("keybool", false));
  m_Config->Set("Author", "myauthor");
  CPPUNIT_ASSERT(m_Config->Get("Author", "yourauthor") == "myauthor");

  // test wxExFile
  CPPUNIT_ASSERT(m_File->GetStat().IsOk());
  CPPUNIT_ASSERT(m_File->GetStat().GetFullPath() == m_File->GetFileName().GetFullPath());
  // The fullpath should be normalized, test it.
  CPPUNIT_ASSERT(m_File->GetFileName().GetFullPath() != TEST_FILE);
  CPPUNIT_ASSERT(!m_File->GetStat().IsReadOnly());
  CPPUNIT_ASSERT(!m_File->CheckFileSync());
  CPPUNIT_ASSERT(!m_File->GetStat().IsReadOnly());
  CPPUNIT_ASSERT(m_File->FileOpen(wxExFileName(TEST_BIN)));
  wxCharBuffer buffer = m_File->Read();
  CPPUNIT_ASSERT(buffer.length() == 40);

  // test wxExFileName
  CPPUNIT_ASSERT(m_FileName->GetLexer().GetScintillaLexer().empty());
  CPPUNIT_ASSERT(m_FileName->GetStat().IsOk());
  m_FileName->Assign("xxx");
  m_FileName->GetStat().Sync("xxx");
  CPPUNIT_ASSERT(!m_FileName->GetStat().IsOk());

  // test wxExFileNameStatistics
  CPPUNIT_ASSERT(m_FileNameStatistics->Get().empty());
  CPPUNIT_ASSERT(m_FileNameStatistics->Get("xx") == 0);

  // test wxExLexer
  *m_Lexer = m_Lexers->FindByText("// this is a cpp comment text");
  CPPUNIT_ASSERT(m_Lexer->GetScintillaLexer().empty()); // we have no lexers
  // now read lexers
  CPPUNIT_ASSERT(m_Lexers->Read());
  *m_Lexer = m_Lexers->FindByText("// this is a cpp comment text");
  CPPUNIT_ASSERT(!m_Lexer->GetAssociations().empty());
  CPPUNIT_ASSERT(!m_Lexer->GetColourings().empty());
  CPPUNIT_ASSERT(!m_Lexer->GetCommentBegin().empty());
  CPPUNIT_ASSERT(!m_Lexer->GetCommentBegin2().empty());
  CPPUNIT_ASSERT(m_Lexer->GetCommentEnd().empty());
  CPPUNIT_ASSERT(!m_Lexer->GetCommentEnd2().empty());
  CPPUNIT_ASSERT(!m_Lexer->GetKeywords().empty());
  CPPUNIT_ASSERT(!m_Lexer->GetKeywordsSet().empty());
  CPPUNIT_ASSERT(!m_Lexer->GetKeywordsString().empty());
  CPPUNIT_ASSERT(!m_Lexer->GetProperties().empty());
  CPPUNIT_ASSERT(m_Lexer->IsKeyword("class"));
  CPPUNIT_ASSERT(m_Lexer->IsKeyword("const"));
  CPPUNIT_ASSERT(m_Lexer->KeywordStartsWith("cla"));
  CPPUNIT_ASSERT(!m_Lexer->KeywordStartsWith("xxx"));
  CPPUNIT_ASSERT(!m_Lexer->MakeComment("test", true).empty());
  CPPUNIT_ASSERT(!m_Lexer->MakeComment("test", "test").empty());
  CPPUNIT_ASSERT(m_Lexer->SetKeywords("hello:1"));
  CPPUNIT_ASSERT(m_Lexer->SetKeywords("test11 test21:1 test31:1 test12:2 test22:2"));
  CPPUNIT_ASSERT(!m_Lexer->IsKeyword("class")); // now overwritten
  CPPUNIT_ASSERT(m_Lexer->IsKeyword("test11"));
  CPPUNIT_ASSERT(m_Lexer->IsKeyword("test21"));
  CPPUNIT_ASSERT(m_Lexer->IsKeyword("test12"));
  CPPUNIT_ASSERT(m_Lexer->IsKeyword("test22"));
  CPPUNIT_ASSERT(m_Lexer->KeywordStartsWith("te"));
  CPPUNIT_ASSERT(!m_Lexer->KeywordStartsWith("xx"));
  CPPUNIT_ASSERT(!m_Lexer->GetKeywords().empty());
  CPPUNIT_ASSERT(!m_Lexer->GetKeywordsSet().empty());

  // test wxExLexers
  CPPUNIT_ASSERT(!m_Lexers->BuildComboBox().empty());
  CPPUNIT_ASSERT(!m_Lexers->BuildWildCards(wxFileName(TEST_FILE)).empty());
  CPPUNIT_ASSERT(m_Lexers->Count() > 0);
  CPPUNIT_ASSERT(m_Lexers->FindByFileName(wxFileName(TEST_FILE)).GetScintillaLexer() == "cpp");
  CPPUNIT_ASSERT(m_Lexers->FindByName("cpp").GetScintillaLexer() == "cpp");
  CPPUNIT_ASSERT(m_Lexers->FindByText("// this is a cpp comment text").GetScintillaLexer() == "cpp");
  CPPUNIT_ASSERT(!m_Lexers->GetIndicators().empty());
  CPPUNIT_ASSERT(!m_Lexers->GetMarkers().empty());
  CPPUNIT_ASSERT(!m_Lexers->GetStyles().empty());
  CPPUNIT_ASSERT(!m_Lexers->GetStylesHex().empty());

  // test wxExRCS
  CPPUNIT_ASSERT(m_RCS->GetDescription().empty());
  CPPUNIT_ASSERT(m_RCS->GetUser().empty());

  // test wxExStat
  CPPUNIT_ASSERT(m_Stat->IsOk());
  CPPUNIT_ASSERT(!m_Stat->IsReadOnly());
  CPPUNIT_ASSERT(m_Stat->Sync("./test-base.link"));

  // test wxExStatistics
  m_Statistics->Inc("test");
  CPPUNIT_ASSERT(m_Statistics->Get("test") == 1);
  m_Statistics->Inc("test");
  CPPUNIT_ASSERT(m_Statistics->Get("test") == 2);
  m_Statistics->Set("test", 13);
  CPPUNIT_ASSERT(m_Statistics->Get("test") == 13);
  m_Statistics->Dec("test");
  CPPUNIT_ASSERT(m_Statistics->Get("test") == 12);
  m_Statistics->Inc("test2");
  CPPUNIT_ASSERT(m_Statistics->Get("test2") == 1);
  const wxExStatistics<long> copy(*m_Statistics);
  CPPUNIT_ASSERT(copy.Get("test2") == 1);
  m_Statistics->Clear();
  CPPUNIT_ASSERT(m_Statistics->GetItems().empty());

  // test wxExTextFile
  wxExTextFile textFile(wxExFileName(TEST_FILE), ID_TOOL_REPORT_COUNT, m_Config);
  CPPUNIT_ASSERT(textFile.RunTool());
  CPPUNIT_ASSERT(!textFile.GetStatistics().GetElements().GetItems().empty());
  CPPUNIT_ASSERT(!textFile.IsOpened()); // file should be closed after running tool

  CPPUNIT_ASSERT(textFile.RunTool()); // do the same test
  CPPUNIT_ASSERT(!textFile.GetStatistics().GetElements().GetItems().empty());
  CPPUNIT_ASSERT(!textFile.IsOpened()); // file should be closed after running tool

  wxExTextFile textFile2(wxExFileName(TEST_FILE), ID_TOOL_REPORT_KEYWORD, m_Config);
  CPPUNIT_ASSERT(textFile2.RunTool());
//  CPPUNIT_ASSERT(!m_TextFile->GetStatistics().GetKeywords().GetItems().empty());

  // test wxExTool
  CPPUNIT_ASSERT(wxExTool(ID_TOOL_REPORT_COUNT).IsCount());
  CPPUNIT_ASSERT(wxExTool(ID_TOOL_REPORT_FIND).IsFindType());
  CPPUNIT_ASSERT(wxExTool(ID_TOOL_REPORT_REPLACE).IsFindType());
  CPPUNIT_ASSERT(wxExTool(ID_TOOL_REPORT_COUNT).IsStatisticsType());
  CPPUNIT_ASSERT(wxExTool(ID_TOOL_REPORT_COUNT).IsReportType());
  CPPUNIT_ASSERT(wxExTool::GetToolInfo().empty()); // initialized by wxExApp, so not here
}

void wxExTestFixture::testTiming()
{
  wxExFile file(TEST_FILE);

  CPPUNIT_ASSERT(file.IsOpened());

  wxStopWatch sw;

  const int max = 10000;

  for (int i = 0; i < max; i++)
  {
    CPPUNIT_ASSERT(file.Read().length() > 0);
  }

  const long exfile_read = sw.Time();

  sw.Start();

  wxFile wxfile(TEST_FILE);

  for (int j = 0; j < max; j++)
  {
    char* charbuffer = new char[wxfile.Length()];
    wxfile.Read(charbuffer, wxfile.Length());
    wxString* buffer = new wxString(charbuffer, wxfile.Length());
    CPPUNIT_ASSERT(buffer->length() > 0);
    delete charbuffer;
    delete buffer;
  }

  const long file_read = sw.Time();

  printf(
    "wxExFile::Read:%ld wxFile::Read:%ld\n",
    exfile_read,
    file_read);
}

void wxExTestFixture::testTimingAttrib()
{
  const int max = 1000;

  wxStopWatch sw;

  const wxExFileName exfile(TEST_FILE);

  int checked = 0;

  for (int i = 0; i < max; i++)
  {
    checked += exfile.GetStat().IsReadOnly();
  }

  const long exfile_time = sw.Time();

  sw.Start();

  const wxFileName file(TEST_FILE);

  for (int j = 0; j < max; j++)
  {
    checked += file.IsFileWritable();
  }

  const long file_time = sw.Time();

  printf(
    "wxExFileName::IsReadOnly:%ld wxFileName::IsFileWritable:%ld\n",
    exfile_time,
    file_time);
}

void wxExTestFixture::testTimingConfig()
{
  const int max = 100000;

  wxStopWatch sw;

  for (int i = 0; i < max; i++)
  {
    m_Config->Get("test", 0);
  }

  const long exconfig = sw.Time();

  sw.Start();

  for (int j = 0; j < max; j++)
  {
    m_Config->Read("test", 0l);
  }

  const long config = sw.Time();

  printf(
    "wxExConfig::Get:%ld wxConfig::Read:%ld\n",
    exconfig,
    config);
}

void wxExTestFixture::tearDown()
{
}

wxExTestSuite::wxExTestSuite()
  : CppUnit::TestSuite("wxextension test suite")
{
  // Add the tests.
  addTest(new CppUnit::TestCaller<wxExTestFixture>(
    "testConstructors",
    &wxExTestFixture::testConstructors));

  addTest(new CppUnit::TestCaller<wxExTestFixture>(
    "testMethods",
    &wxExTestFixture::testMethods));

  addTest(new CppUnit::TestCaller<wxExTestFixture>(
    "testTiming",
    &wxExTestFixture::testTiming));

  addTest(new CppUnit::TestCaller<wxExTestFixture>(
    "testTimingAttrib",
    &wxExTestFixture::testTimingAttrib));

  addTest(new CppUnit::TestCaller<wxExTestFixture>(
    "testTimingConfig",
    &wxExTestFixture::testTimingConfig));
}
<commit_msg>fix compile errors due to new API<commit_after>/******************************************************************************\
* File:          test.cpp
* Purpose:       Implementation for wxextension cpp unit testing
* Author:        Anton van Wezenbeek
* RCS-ID:        $Id$
* Created:       za 17 jan 2009 11:51:20 CET
*
* Copyright (c) 2009 Anton van Wezenbeek
* All rights are reserved. Reproduction in whole or part is prohibited
* without the written consent of the copyright owner.
\******************************************************************************/

#include <TestCaller.h>
#include "test.h"

#define TEST_FILE "./test.h"
#define TEST_BIN "./test.bin"

class wxExFileTest: public wxExFile
{
public :
  wxExFileTest() {;};
private:
  virtual bool GetContentsChanged() {return false;};
  virtual void ResetContentsChanged() {;};
  virtual void DoFileLoad(bool) {;};
  virtual void DoFileSave() {;};
};

void wxExTestFixture::setUp()
{
  m_Config = new wxExConfig("test.cfg", wxCONFIG_USE_LOCAL_FILE);
  m_File = new wxExFile(TEST_FILE);
  m_FileName = new wxExFileName(TEST_FILE);
  m_FileNameStatistics = new wxExFileNameStatistics(TEST_FILE);
  m_Lexer = new wxExLexer();
  m_Lexers = new wxExLexers(wxFileName("../extension/data/lexers.xml"));
  m_RCS = new wxExRCS();
  m_Stat = new wxExStat(TEST_FILE);
  m_Statistics = new wxExStatistics<long>();
}

void wxExTestFixture::testConstructors()
{
  CPPUNIT_ASSERT(m_File != NULL);
}

void wxExTestFixture::testMethods()
{
  // test wxExConfig
  CPPUNIT_ASSERT(m_Config->Get("keystring", "val") == "val");
  CPPUNIT_ASSERT(m_Config->Get("keylong", 12) == 12);
  CPPUNIT_ASSERT(m_Config->GetBool("keybool", true));
  CPPUNIT_ASSERT(m_Config->GetFindReplaceData() != NULL);
  m_Config->Set("keystring", "val2");
  CPPUNIT_ASSERT(m_Config->Get("keystring", "val") == "val2");
  m_Config->Set("keylong", 15);
  CPPUNIT_ASSERT(m_Config->Get("keylong", 7) == 15);
  m_Config->Set("keybool", false);
  CPPUNIT_ASSERT(m_Config->GetBool("keybool", true) == false);
  m_Config->Toggle("keybool");
  CPPUNIT_ASSERT(m_Config->GetBool("keybool", false));
  m_Config->Set("Author", "myauthor");
  CPPUNIT_ASSERT(m_Config->Get("Author", "yourauthor") == "myauthor");

  // test wxExFile
  CPPUNIT_ASSERT(m_File->GetStat().IsOk());
  CPPUNIT_ASSERT(m_File->GetStat().GetFullPath() == m_File->GetFileName().GetFullPath());
  // The fullpath should be normalized, test it.
  CPPUNIT_ASSERT(m_File->GetFileName().GetFullPath() != TEST_FILE);
  CPPUNIT_ASSERT(!m_File->GetStat().IsReadOnly());
  CPPUNIT_ASSERT(!m_File->CheckFileSync());
  CPPUNIT_ASSERT(!m_File->GetStat().IsReadOnly());
  CPPUNIT_ASSERT(m_File->FileLoad(wxExFileName(TEST_BIN)));
  wxCharBuffer buffer = m_File->Read();
  CPPUNIT_ASSERT(buffer.length() == 40);

  // test wxExFileName
  CPPUNIT_ASSERT(m_FileName->GetLexer().GetScintillaLexer().empty());
  CPPUNIT_ASSERT(m_FileName->GetStat().IsOk());
  m_FileName->Assign("xxx");
  m_FileName->GetStat().Sync("xxx");
  CPPUNIT_ASSERT(!m_FileName->GetStat().IsOk());

  // test wxExFileNameStatistics
  CPPUNIT_ASSERT(m_FileNameStatistics->Get().empty());
  CPPUNIT_ASSERT(m_FileNameStatistics->Get("xx") == 0);

  // test wxExLexer
  *m_Lexer = m_Lexers->FindByText("// this is a cpp comment text");
  CPPUNIT_ASSERT(m_Lexer->GetScintillaLexer().empty()); // we have no lexers
  // now read lexers
  CPPUNIT_ASSERT(m_Lexers->Read());
  *m_Lexer = m_Lexers->FindByText("// this is a cpp comment text");
  CPPUNIT_ASSERT(!m_Lexer->GetAssociations().empty());
  CPPUNIT_ASSERT(!m_Lexer->GetColourings().empty());
  CPPUNIT_ASSERT(!m_Lexer->GetCommentBegin().empty());
  CPPUNIT_ASSERT(!m_Lexer->GetCommentBegin2().empty());
  CPPUNIT_ASSERT(m_Lexer->GetCommentEnd().empty());
  CPPUNIT_ASSERT(!m_Lexer->GetCommentEnd2().empty());
  CPPUNIT_ASSERT(!m_Lexer->GetKeywords().empty());
  CPPUNIT_ASSERT(!m_Lexer->GetKeywordsSet().empty());
  CPPUNIT_ASSERT(!m_Lexer->GetKeywordsString().empty());
  CPPUNIT_ASSERT(!m_Lexer->GetProperties().empty());
  CPPUNIT_ASSERT(m_Lexer->IsKeyword("class"));
  CPPUNIT_ASSERT(m_Lexer->IsKeyword("const"));
  CPPUNIT_ASSERT(m_Lexer->KeywordStartsWith("cla"));
  CPPUNIT_ASSERT(!m_Lexer->KeywordStartsWith("xxx"));
  CPPUNIT_ASSERT(!m_Lexer->MakeComment("test", true).empty());
  CPPUNIT_ASSERT(!m_Lexer->MakeComment("test", "test").empty());
  CPPUNIT_ASSERT(m_Lexer->SetKeywords("hello:1"));
  CPPUNIT_ASSERT(m_Lexer->SetKeywords("test11 test21:1 test31:1 test12:2 test22:2"));
  CPPUNIT_ASSERT(!m_Lexer->IsKeyword("class")); // now overwritten
  CPPUNIT_ASSERT(m_Lexer->IsKeyword("test11"));
  CPPUNIT_ASSERT(m_Lexer->IsKeyword("test21"));
  CPPUNIT_ASSERT(m_Lexer->IsKeyword("test12"));
  CPPUNIT_ASSERT(m_Lexer->IsKeyword("test22"));
  CPPUNIT_ASSERT(m_Lexer->KeywordStartsWith("te"));
  CPPUNIT_ASSERT(!m_Lexer->KeywordStartsWith("xx"));
  CPPUNIT_ASSERT(!m_Lexer->GetKeywords().empty());
  CPPUNIT_ASSERT(!m_Lexer->GetKeywordsSet().empty());

  // test wxExLexers
  CPPUNIT_ASSERT(!m_Lexers->BuildComboBox().empty());
  CPPUNIT_ASSERT(!m_Lexers->BuildWildCards(wxFileName(TEST_FILE)).empty());
  CPPUNIT_ASSERT(m_Lexers->Count() > 0);
  CPPUNIT_ASSERT(m_Lexers->FindByFileName(wxFileName(TEST_FILE)).GetScintillaLexer() == "cpp");
  CPPUNIT_ASSERT(m_Lexers->FindByName("cpp").GetScintillaLexer() == "cpp");
  CPPUNIT_ASSERT(m_Lexers->FindByText("// this is a cpp comment text").GetScintillaLexer() == "cpp");
  CPPUNIT_ASSERT(!m_Lexers->GetIndicators().empty());
  CPPUNIT_ASSERT(!m_Lexers->GetMarkers().empty());
  CPPUNIT_ASSERT(!m_Lexers->GetStyles().empty());
  CPPUNIT_ASSERT(!m_Lexers->GetStylesHex().empty());

  // test wxExRCS
  CPPUNIT_ASSERT(m_RCS->GetDescription().empty());
  CPPUNIT_ASSERT(m_RCS->GetUser().empty());

  // test wxExStat
  CPPUNIT_ASSERT(m_Stat->IsOk());
  CPPUNIT_ASSERT(!m_Stat->IsReadOnly());
  CPPUNIT_ASSERT(m_Stat->Sync("./test-base.link"));

  // test wxExStatistics
  m_Statistics->Inc("test");
  CPPUNIT_ASSERT(m_Statistics->Get("test") == 1);
  m_Statistics->Inc("test");
  CPPUNIT_ASSERT(m_Statistics->Get("test") == 2);
  m_Statistics->Set("test", 13);
  CPPUNIT_ASSERT(m_Statistics->Get("test") == 13);
  m_Statistics->Dec("test");
  CPPUNIT_ASSERT(m_Statistics->Get("test") == 12);
  m_Statistics->Inc("test2");
  CPPUNIT_ASSERT(m_Statistics->Get("test2") == 1);
  const wxExStatistics<long> copy(*m_Statistics);
  CPPUNIT_ASSERT(copy.Get("test2") == 1);
  m_Statistics->Clear();
  CPPUNIT_ASSERT(m_Statistics->GetItems().empty());

  // test wxExTextFile
  wxExTextFile textFile(wxExFileName(TEST_FILE), ID_TOOL_REPORT_COUNT, m_Config);
  CPPUNIT_ASSERT(textFile.RunTool());
  CPPUNIT_ASSERT(!textFile.GetStatistics().GetElements().GetItems().empty());
  CPPUNIT_ASSERT(!textFile.IsOpened()); // file should be closed after running tool

  CPPUNIT_ASSERT(textFile.RunTool()); // do the same test
  CPPUNIT_ASSERT(!textFile.GetStatistics().GetElements().GetItems().empty());
  CPPUNIT_ASSERT(!textFile.IsOpened()); // file should be closed after running tool

  wxExTextFile textFile2(wxExFileName(TEST_FILE), ID_TOOL_REPORT_KEYWORD, m_Config);
  CPPUNIT_ASSERT(textFile2.RunTool());
//  CPPUNIT_ASSERT(!m_TextFile->GetStatistics().GetKeywords().GetItems().empty());

  // test wxExTool
  CPPUNIT_ASSERT(wxExTool(ID_TOOL_REPORT_COUNT).IsCount());
  CPPUNIT_ASSERT(wxExTool(ID_TOOL_REPORT_FIND).IsFindType());
  CPPUNIT_ASSERT(wxExTool(ID_TOOL_REPORT_REPLACE).IsFindType());
  CPPUNIT_ASSERT(wxExTool(ID_TOOL_REPORT_COUNT).IsStatisticsType());
  CPPUNIT_ASSERT(wxExTool(ID_TOOL_REPORT_COUNT).IsReportType());
  CPPUNIT_ASSERT(wxExTool::GetToolInfo().empty()); // initialized by wxExApp, so not here
}

void wxExTestFixture::testTiming()
{
  wxExFile file(TEST_FILE);

  CPPUNIT_ASSERT(file.IsOpened());

  wxStopWatch sw;

  const int max = 10000;

  for (int i = 0; i < max; i++)
  {
    CPPUNIT_ASSERT(file.Read().length() > 0);
  }

  const long exfile_read = sw.Time();

  sw.Start();

  wxFile wxfile(TEST_FILE);

  for (int j = 0; j < max; j++)
  {
    char* charbuffer = new char[wxfile.Length()];
    wxfile.Read(charbuffer, wxfile.Length());
    wxString* buffer = new wxString(charbuffer, wxfile.Length());
    CPPUNIT_ASSERT(buffer->length() > 0);
    delete charbuffer;
    delete buffer;
  }

  const long file_read = sw.Time();

  printf(
    "wxExFile::Read:%ld wxFile::Read:%ld\n",
    exfile_read,
    file_read);
}

void wxExTestFixture::testTimingAttrib()
{
  const int max = 1000;

  wxStopWatch sw;

  const wxExFileName exfile(TEST_FILE);

  int checked = 0;

  for (int i = 0; i < max; i++)
  {
    checked += exfile.GetStat().IsReadOnly();
  }

  const long exfile_time = sw.Time();

  sw.Start();

  const wxFileName file(TEST_FILE);

  for (int j = 0; j < max; j++)
  {
    checked += file.IsFileWritable();
  }

  const long file_time = sw.Time();

  printf(
    "wxExFileName::IsReadOnly:%ld wxFileName::IsFileWritable:%ld\n",
    exfile_time,
    file_time);
}

void wxExTestFixture::testTimingConfig()
{
  const int max = 100000;

  wxStopWatch sw;

  for (int i = 0; i < max; i++)
  {
    m_Config->Get("test", 0);
  }

  const long exconfig = sw.Time();

  sw.Start();

  for (int j = 0; j < max; j++)
  {
    m_Config->Read("test", 0l);
  }

  const long config = sw.Time();

  printf(
    "wxExConfig::Get:%ld wxConfig::Read:%ld\n",
    exconfig,
    config);
}

void wxExTestFixture::tearDown()
{
}

wxExTestSuite::wxExTestSuite()
  : CppUnit::TestSuite("wxextension test suite")
{
  // Add the tests.
  addTest(new CppUnit::TestCaller<wxExTestFixture>(
    "testConstructors",
    &wxExTestFixture::testConstructors));

  addTest(new CppUnit::TestCaller<wxExTestFixture>(
    "testMethods",
    &wxExTestFixture::testMethods));

  addTest(new CppUnit::TestCaller<wxExTestFixture>(
    "testTiming",
    &wxExTestFixture::testTiming));

  addTest(new CppUnit::TestCaller<wxExTestFixture>(
    "testTimingAttrib",
    &wxExTestFixture::testTimingAttrib));

  addTest(new CppUnit::TestCaller<wxExTestFixture>(
    "testTimingConfig",
    &wxExTestFixture::testTimingConfig));
}
<|endoftext|>


<commit_before>// Halide tutorial lesson 4

// This lesson demonstrates how to follow what Halide is doing at runtime.

// This lesson can be built by invoking the command:
//    make tutorial_lesson_04_debugging_2
// in a shell with the current directory at the top of the halide source tree.
// Otherwise, see the platform-specific compiler invocations below.

// On linux, you can compile and run it like so:
// g++ lesson_04*.cpp -g -I ../include -L ../bin -lHalide -lpthread -ldl -o lesson_04 -std=c++11
// LD_LIBRARY_PATH=../bin ./lesson_04

// On os x:
// g++ lesson_04*.cpp -g -I ../include -L ../bin -lHalide -o lesson_04 -std=c++11
// DYLD_LIBRARY_PATH=../bin ./lesson_04

#include "Halide.h"
#include <stdio.h>
using namespace Halide;

int main(int argc, char **argv) {

    Func gradient("gradient");
    Var x("x"), y("y");

    // We'll define our gradient function as before.
    gradient(x, y) = x + y;

    // And tell Halide that we'd like to be notified of all
    // evaluations.
    gradient.trace_stores();

    // Realize the function over an 8x8 region.
    printf("Evaluating gradient\n");
    Image<int> output = gradient.realize(8, 8);

    // This will print out all the times gradient(x, y) gets
    // evaluated.

    // Now that we can snoop on what Halide is doing, let's try our
    // first scheduling primitive. We'll make a new version of
    // gradient that processes each scanline in parallel.
    Func parallel_gradient("parallel_gradient");
    parallel_gradient(x, y) = x + y;

    // We'll also trace this function.
    parallel_gradient.trace_stores();

    // Things are the same so far. We've defined the algorithm, but
    // haven't said anything about how to schedule it. In general,
    // exploring different scheduling decisions doesn't change the code
    // that describes the algorithm.

    // Now we tell Halide to use a parallel for loop over the y
    // coordinate. On linux we run this using a thread pool and a task
    // queue. On os x we call into grand central dispatch, which does
    // the same thing for us.
    parallel_gradient.parallel(y);

    // This time the printfs should come out of order, because each
    // scanline is potentially being processed in a different
    // thread. The number of threads should adapt to your system, but
    // on linux you can control it manually using the environment
    // variable HL_NUMTHREADS.
    printf("\nEvaluating parallel_gradient\n");
    parallel_gradient.realize(8, 8);

    printf("Success!\n");
    return 0;
}
<commit_msg>Overhaul debugging 2 to include discussion of print and print_when<commit_after>// Halide tutorial lesson 4

// This lesson demonstrates how to follow what Halide is doing at runtime.

// This lesson can be built by invoking the command:
//    make tutorial_lesson_04_debugging_2
// in a shell with the current directory at the top of the halide source tree.
// Otherwise, see the platform-specific compiler invocations below.

// On linux, you can compile and run it like so:
// g++ lesson_04*.cpp -g -I ../include -L ../bin -lHalide -lpthread -ldl -o lesson_04 -std=c++11
// LD_LIBRARY_PATH=../bin ./lesson_04

// On os x:
// g++ lesson_04*.cpp -g -I ../include -L ../bin -lHalide -o lesson_04 -std=c++11
// DYLD_LIBRARY_PATH=../bin ./lesson_04

#include "Halide.h"
#include <stdio.h>
using namespace Halide;

int main(int argc, char **argv) {

    Var x("x"), y("y");

    // Printing out the value of Funcs as they are computed.
    {
        // We'll define our gradient function as before.
        Func gradient("gradient");
        gradient(x, y) = x + y;

        // And tell Halide that we'd like to be notified of all
        // evaluations.
        gradient.trace_stores();

        // Realize the function over an 8x8 region.
        printf("Evaluating gradient\n");
        Image<int> output = gradient.realize(8, 8);

        // This will print out all the times gradient(x, y) gets
        // evaluated.

        // Now that we can snoop on what Halide is doing, let's try our
        // first scheduling primitive. We'll make a new version of
        // gradient that processes each scanline in parallel.
        Func parallel_gradient("parallel_gradient");
        parallel_gradient(x, y) = x + y;

        // We'll also trace this function.
        parallel_gradient.trace_stores();

        // Things are the same so far. We've defined the algorithm, but
        // haven't said anything about how to schedule it. In general,
        // exploring different scheduling decisions doesn't change the code
        // that describes the algorithm.

        // Now we tell Halide to use a parallel for loop over the y
        // coordinate. On Linux we run this using a thread pool and a task
        // queue. On OS X we call into grand central dispatch, which does
        // the same thing for us.
        parallel_gradient.parallel(y);

        // This time the printfs should come out of order, because each
        // scanline is potentially being processed in a different
        // thread. The number of threads should adapt to your system, but
        // on linux you can control it manually using the environment
        // variable HL_NUM_THREADS.
        printf("\nEvaluating parallel_gradient\n");
        parallel_gradient.realize(8, 8);
    }

    // Printing individual Exprs.
    {
        // trace_stores() can only print the value of a
        // Func. Sometimes you want to inspect the value of
        // sub-expressions rather than the entire Func. The built-in
        // function 'print' can be wrapped around any Expr to print
        // the value of that Expr every time it is evaluated.

        // For example, say we have some Func that is the sum of two terms:
        Func f;
        f(x, y) = sin(x) + cos(y);

        // If we want to inspect just one of the terms, we can wrap
        // 'print' around it like so:
        Func g;
        g(x, y) = sin(x) + print(cos(y));

        printf("\nEvaluating sin(x) + cos(y), and just printing cos(y)\n");
        g.realize(4, 4);
    }

    // Printing additional context.
    {
        // print can take multiple arguments. It prints all of them
        // and evaluates to the first one. The arguments can be Exprs
        // or constant strings. This can be used to print additional
        // context alongside the value:
        Func f;
        f(x, y) = sin(x) + print(cos(y), "<- this is cos(", y, ") when x =", x);

        printf("\nEvaluating sin(x) + cos(y), and printing cos(y) with more context\n");
        f.realize(4, 4);

        // It can be useful to split expressions like the one above
        // across multiple lines to make it easier to turn on and off
        // printing certain values while debugging.
        Expr e = cos(y);
        // Uncomment the following line to print the value of cos(y)
        // e = print(e, "<- this is cos(", y, ") when x =", x);
        Func g;
        g(x, y) = sin(x) + e;
        g.realize(4, 4);
    }

    // Conditional printing
    {
        // Both print and trace_stores can produce a lot of output. If
        // you're looking for a rare event, or just want to see what
        // happens at a single pixel, this amount of output can be
        // difficult to dig through. Instead, the function print_when
        // can be used to conditionally print an Expr. The first
        // argument to print_when is a boolean Expr. If the Expr
        // evaluates to true, it returns the second argument and
        // prints all of the arguments. If the Expr evaluates to false
        // it just returns the second argument and does not print.

        Func f;
        Expr e = cos(y);
        e = print_when(x == 37 && y == 42, e, "<- this is cos(y) at x, y == (37, 42)");
        f(x, y) = sin(x) + e;
        printf("\nEvaluating sin(x) + cos(y), and printing cos(y) at a single pixel\n");
        f.realize(640, 480);

        // print_when can also be used to check for values you're not expecting:
        Func g;
        e = cos(y);
        e = print_when(e < 0, e, "cos(y) < 0 at y ==", y);
        g(x, y) = sin(x) + e;
        printf("\nEvaluating sin(x) + cos(y), and printing whenever cos(y) < 0\n");
        g.realize(4, 4);
    }

    // Printing expressions at compile-time.
    {
        // The code above builds up a Halide Expr across several lines
        // of code. If you're programmatically aconstructing a complex
        // expression, and you want to check the Expr you've created
        // is what you think it is, you can also print out the
        // expression itself using C++ streams:
        Var fizz("fizz"), buzz("buzz");
        Expr e = 1;
        for (int i = 2; i < 100; i++) {
            if (i % 3 == 0 && i % 5 == 0) e += fizz*buzz;
            else if (i % 3 == 0) e += fizz;
            else if (i % 5 == 0) e += buzz;
            else e += i;
        }
        std::cout << "Printing a complex Expr: " << e << "\n";
    }

    printf("Success!\n");
    return 0;
}
<|endoftext|>


<commit_before>#include <tesseract/baseapi.h>
#include <leptonica/allheaders.h>
#include <string>
#include <libgen.h>

int main(int argc, char *argv[]) {
  if(argc != 3) { printf("USAGE: %s imagefile outputdir", argv[0]); }

  std::string input_filename = std::string(argv[1]);
  std::string input_basename = std::string(basename(argv[1]));

  std::string output_dir = std::string(argv[2]);

  tesseract::TessBaseAPI *api = new tesseract::TessBaseAPI();
  api->Init(NULL, "eng");
  Pix *image0 = pixRead(input_filename.c_str());
  api->SetImage(image0);
  Pix* image = api->GetThresholdedImage();
  api->SetImage(image);
  Boxa* boxes = api->GetComponentImages(tesseract::RIL_TEXTLINE, true, false, 0, NULL, NULL, NULL);
  printf("204c\n");

  printf("Found %d textline image components.\n", boxes->n);

  int lastindex = input_basename.find_last_of(".");
  std::string basename = input_basename.substr(0, lastindex).c_str();
  std::string extension = input_basename.substr(lastindex + 1).c_str();

  std::string outdir = output_dir.c_str();
  int linedirLen = outdir.length()+1+basename.length()+strlen("-line_extract_")+extension.length();
  char* linedir = (char*)malloc((linedirLen+1)*sizeof(char));
  sprintf(linedir, "%s/%s-line_extract_%s", output_dir.c_str(), basename.c_str(), extension.c_str());
  printf("Writing to directory [%s].  If this fails, try:\n    mkdir -p %s\n\n\n", linedir, linedir);

  for (int i = 0; i < boxes->n; i++) {
    BOX* box = boxaGetBox(boxes, i, L_CLONE);
    PIX* pixd= pixClipRectangle(image, box, NULL);

    char* linefilename = (char*)malloc((linedirLen+strlen("/line00.")+extension.length()+1)*sizeof(char));
    sprintf(linefilename, "%s/line%02d.%s", linedir, i, extension.c_str());
    printf("  Writing %s\n", linefilename);
    pixWrite(linefilename, pixd, IFF_DEFAULT);
    pixDestroy(&pixd);
    boxDestroy(&box);
    free(linefilename);
  }

  free(linedir);
  return 0;
}
<commit_msg>Return failure after printing USAGE statement, try to system out to mkdir ourselves<commit_after>#include <tesseract/baseapi.h>
#include <leptonica/allheaders.h>
#include <string>
#include <libgen.h>

int main(int argc, char *argv[]) {
  if(argc != 3) { printf("USAGE: %s imagefile outputdir\n", argv[0]); return 1; }

  std::string input_filename = std::string(argv[1]);
  std::string input_basename = std::string(basename(argv[1]));

  std::string output_dir = std::string(argv[2]);

  tesseract::TessBaseAPI *api = new tesseract::TessBaseAPI();
  api->Init(NULL, "eng");
  Pix *image0 = pixRead(input_filename.c_str());
  api->SetImage(image0);
  Pix* image = api->GetThresholdedImage();
  api->SetImage(image);
  Boxa* boxes = api->GetComponentImages(tesseract::RIL_TEXTLINE, true, false, 0, NULL, NULL, NULL);

  printf("Found %d textline image components.\n", boxes->n);

  int lastindex = input_basename.find_last_of(".");
  std::string basename = input_basename.substr(0, lastindex).c_str();
  std::string extension = input_basename.substr(lastindex + 1).c_str();

  std::string outdir = output_dir.c_str();
  int linedirLen = outdir.length()+1+basename.length()+strlen("-line_extract_")+extension.length();
  char* linedir = (char*)malloc((linedirLen+1)*sizeof(char));
  sprintf(linedir, "%s/%s-line_extract_%s", output_dir.c_str(), basename.c_str(), extension.c_str());
  printf("Writing to directory [%s].  If this fails, try:\n    mkdir -p %s\n\n\n", linedir, linedir);
  std::string mkdir_cmd = "mkdir -p " + std::string(linedir);
  system(mkdir_cmd.c_str());

  for (int i = 0; i < boxes->n; i++) {
    BOX* box = boxaGetBox(boxes, i, L_CLONE);
    PIX* pixd= pixClipRectangle(image, box, NULL);

    char* linefilename = (char*)malloc((linedirLen+strlen("/line00.")+extension.length()+1)*sizeof(char));
    sprintf(linefilename, "%s/line%02d.%s", linedir, i, extension.c_str());
    printf("  Writing %s\n", linefilename);
    pixWrite(linefilename, pixd, IFF_DEFAULT);
    pixDestroy(&pixd);
    boxDestroy(&box);
    free(linefilename);
  }

  free(linedir);
  return 0;
}
<|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 "logjoin/stages/SessionJoin.h"
#include "logjoin/common.h"

using namespace stx;

namespace cm {

void SessionJoin::process(RefPtr<SessionContext> ctx) {

  /* load builtin events into structured format */
  std::vector<TrackedQuery> queries;
  std::vector<TrackedItemVisit> page_views;
  std::vector<TrackedCartItem> cart_items;

  for (const auto& ev : ctx->events) {
    if (ev.evtype == "_search_query") {
      processSearchQueryEvent(ev, &queries);
      continue;
    }

    if (ev.evtype == "_pageview") {
      processPageViewEvent(ev, &page_views);
      continue;
    }

    if (ev.evtype == "_cart_items") {
      processCartItemsEvent(ev, &cart_items);
      continue;
    }
  }

  /* update queries (mark items as clicked) */
  for (auto& cur_query : queries) {

    /* search for matching item visits */
    for (auto& cur_visit : page_views) {
      auto cutoff = cur_query.time.unixMicros() +
          kMaxQueryClickDelaySeconds * kMicrosPerSecond;

      if (cur_visit.time < cur_query.time ||
          cur_visit.time.unixMicros() > cutoff) {
        continue;
      }

      for (auto& qitem : cur_query.items) {
        if (cur_visit.item == qitem.item) {
          qitem.clicked = true;
          qitem.seen = true;
          break;
        }
      }
    }
  }

  /* calculate global gmv */
  uint32_t num_cart_items = 0;
  uint32_t num_order_items = 0;
  uint32_t gmv_eurcents = 0;
  uint32_t cart_value_eurcents = 0;
  HashMap<String, uint64_t> cart_eurcents_per_item;
  HashMap<String, uint64_t> gmv_eurcents_per_item;
  for (const auto& ci : cart_items) {
    auto currency = currencyFromString(ci.currency);
    auto eur = cconv()->convert(Money(ci.price_cents, currency), CURRENCY_EUR);
    auto eurcents = eur.cents;
    eurcents *= ci.quantity;
    cart_eurcents_per_item.emplace(ci.item.docID().docid, eurcents);

    ++num_cart_items;
    cart_value_eurcents += eurcents;
    if (ci.checkout_step == 1) {
      gmv_eurcents_per_item.emplace(ci.item.docID().docid, eurcents);
      ++num_order_items;
      gmv_eurcents += eurcents;
    }
  }

  /* calculate gmv and ctrs per query */
  for (auto& q : queries) {
    auto slrid = extractAttr(q.attrs, "slrid");

    for (auto& i : q.items) {
      // DAWANDA HACK
      if (i.position >= 1 && i.position <= 4 && slrid.isEmpty()) {
        ++q.nads;
        q.nadclicks += i.clicked;
      }
      // EOF DAWANDA HACK

      ++q.nitems;

      if (i.clicked) {
        ++q.nclicks;

        {
          auto ci = cart_eurcents_per_item.find(i.item.docID().docid);
          if (ci != cart_eurcents_per_item.end()) {
            ++q.num_cart_items;
            q.cart_value_eurcents += ci->second;
          }
        }

        {
          auto ci = gmv_eurcents_per_item.find(i.item.docID().docid);
          if (ci != gmv_eurcents_per_item.end()) {
            ++q.num_order_items;
            q.gmv_eurcents += ci->second;
          }
        }
      }
    }
  }

  for (const auto& ci : cart_items) {
    auto& ciobj = ctx->addOutputEvent(
        ci.time,
        SHA1::compute(ctx->uuid + "~" + ci.item.docID().docid),
        "cart_items")->obj;

    ciobj.addUInt32Field("time", ci.time.unixMicros() / kMicrosPerSecond);
    ciobj.addField("item_id", ci.item.docID().docid);
    ciobj.addUInt32Field("quantity", ci.quantity);
    ciobj.addUInt32Field("price_cents", ci.price_cents);
    ciobj.addUInt32Field("currency", (uint32_t) currencyFromString(ci.currency));
    ciobj.addUInt32Field("checkout_step", ci.checkout_step);
  }

  for (const auto& q : queries) {
    auto& qobj = ctx->addOutputEvent(
        q.time,
        SHA1::compute(ctx->uuid + "~" + q.clickid),
        "search_query")->obj;

    qobj.addUInt32Field("time", q.time.unixMicros() / kMicrosPerSecond);
    qobj.addUInt32Field("language", (uint32_t) cm::extractLanguage(q.attrs));

    auto qstr = cm::extractQueryString(q.attrs);
    if (!qstr.isEmpty()) {
      qobj.addStringField("query_string", qstr.get());
    }

    auto slrid = cm::extractAttr(q.attrs, "slrid");
    if (!slrid.isEmpty()) {
      qobj.addField("shop_id", slrid.get());
    }

    qobj.addUInt32Field("num_result_items", q.nitems);
    qobj.addUInt32Field("num_result_items_clicked", q.nclicks);
    qobj.addUInt32Field("num_ad_impressions", q.nads);
    qobj.addUInt32Field("num_ad_clicks", q.nadclicks);
    qobj.addUInt32Field("num_cart_items", q.num_cart_items);
    qobj.addUInt32Field("cart_value_eurcents", q.cart_value_eurcents);
    qobj.addUInt32Field("num_order_items", q.num_order_items);
    qobj.addUInt32Field("gmv_eurcents", q.gmv_eurcents);

    auto pg_str = cm::extractAttr(q.attrs, "pg");
    if (!pg_str.isEmpty()) {
      qobj.addField("ab_page", pg_str.get());
    }

    auto abgrp = cm::extractABTestGroup(q.attrs);
    if (!abgrp.isEmpty()) {
      qobj.addField("ab_test_group", StringUtil::toString(abgrp.get()));
    }

    auto qcat1 = cm::extractAttr(q.attrs, "q_cat1");
    if (!qcat1.isEmpty()) {
      qobj.addField("category1", qcat1.get());
    }

    auto qcat2 = cm::extractAttr(q.attrs, "q_cat2");
    if (!qcat2.isEmpty()) {
      qobj.addField("category2", qcat2.get());
    }

    auto qcat3 = cm::extractAttr(q.attrs, "q_cat3");
    if (!qcat3.isEmpty()) {
      qobj.addField("category3", qcat3.get());
    }

    auto page_type = extractPageType(q.attrs);
    String query_type = pageTypeToString((PageType) page_type);
    auto qtype_attr = cm::extractAttr(q.attrs, "qt");
    if (!qtype_attr.isEmpty()) {
      query_type = qtype_attr.get();
    }

    qobj.addUInt32Field("device_type", (uint32_t) extractDeviceType(q.attrs));
    qobj.addUInt32Field("page_type", (uint32_t) page_type);
    qobj.addStringField("query_type", query_type);

    for (const auto& item : q.items) {
      qobj.addObject("result_items", [&item] (msg::DynamicMessage* ev) {
        ev->addUInt32Field("position", item.position);
        ev->addStringField("item_id", item.item.docID().docid);
        ev->addBoolField("clicked", item.clicked);
        ev->addBoolField("seen", item.seen);
      });
    }
  }

  for (const auto& iv : page_views) {
    auto& ivobj = ctx->addOutputEvent(
        iv.time,
        SHA1::compute(ctx->uuid + "~" + iv.clickid),
        "page_view")->obj;

    ivobj.addUInt32Field("time", iv.time.unixMicros() / kMicrosPerSecond);
    ivobj.addField("item_id", iv.item.docID().docid);
  }

  ctx->setAttribute("num_cart_items", StringUtil::toString(num_cart_items));
  ctx->setAttribute("cart_value_eurcents", StringUtil::toString(cart_value_eurcents));
  ctx->setAttribute("num_order_items", StringUtil::toString(num_order_items));
  ctx->setAttribute("gmv_eurcents", StringUtil::toString(gmv_eurcents));
}

void SessionJoin::processSearchQueryEvent(
    const TrackedEvent& event,
    Vector<TrackedQuery>* queries) {
  TrackedQuery query;
  query.time = event.time;
  query.clickid = event.evid;

  URI::ParamList logline;
  URI::parseQueryString(event.data, &logline);
  query.fromParams(logline);

  for (auto& q : *queries) {
    if (q.clickid == query.clickid) {
      q.merge(query);
      return;
    }
  }

  queries->emplace_back(query);
}

void SessionJoin::processPageViewEvent(
    const TrackedEvent& event,
    Vector<TrackedItemVisit>* page_views) {
  TrackedItemVisit visit;
  visit.time = event.time;
  visit.clickid = event.evid;

  URI::ParamList logline;
  URI::parseQueryString(event.data, &logline);
  visit.fromParams(logline);

  for (auto& v : *page_views) {
    if (v.clickid == visit.clickid) {
      v.merge(visit);
      return;
    }
  }

  page_views->emplace_back(visit);
}

void SessionJoin::processCartItemsEvent(
    const TrackedEvent& event,
    Vector<TrackedCartItem>* cart_items) {
  URI::ParamList logline;
  URI::parseQueryString(event.data, &logline);

  auto new_cart_items = TrackedCartItem::fromParams(logline);
  for (auto& ci : new_cart_items) {
    ci.time = event.time;
  }

  for (const auto& cart_item : new_cart_items) {
    bool merged = false;

    for (auto& c : *cart_items) {
      if (c.item == cart_item.item) {
        c.merge(cart_item);
        merged = true;
        break;
      }
    }

    if (!merged) {
      cart_items->emplace_back(cart_item);
    }
  }
}

} // namespace cm

<commit_msg>time fields in logjoin<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 "logjoin/stages/SessionJoin.h"
#include "logjoin/common.h"

using namespace stx;

namespace cm {

void SessionJoin::process(RefPtr<SessionContext> ctx) {

  /* load builtin events into structured format */
  std::vector<TrackedQuery> queries;
  std::vector<TrackedItemVisit> page_views;
  std::vector<TrackedCartItem> cart_items;

  for (const auto& ev : ctx->events) {
    if (ev.evtype == "_search_query") {
      processSearchQueryEvent(ev, &queries);
      continue;
    }

    if (ev.evtype == "_pageview") {
      processPageViewEvent(ev, &page_views);
      continue;
    }

    if (ev.evtype == "_cart_items") {
      processCartItemsEvent(ev, &cart_items);
      continue;
    }
  }

  /* update queries (mark items as clicked) */
  for (auto& cur_query : queries) {

    /* search for matching item visits */
    for (auto& cur_visit : page_views) {
      auto cutoff = cur_query.time.unixMicros() +
          kMaxQueryClickDelaySeconds * kMicrosPerSecond;

      if (cur_visit.time < cur_query.time ||
          cur_visit.time.unixMicros() > cutoff) {
        continue;
      }

      for (auto& qitem : cur_query.items) {
        if (cur_visit.item == qitem.item) {
          qitem.clicked = true;
          qitem.seen = true;
          break;
        }
      }
    }
  }

  /* calculate global gmv */
  uint32_t num_cart_items = 0;
  uint32_t num_order_items = 0;
  uint32_t gmv_eurcents = 0;
  uint32_t cart_value_eurcents = 0;
  HashMap<String, uint64_t> cart_eurcents_per_item;
  HashMap<String, uint64_t> gmv_eurcents_per_item;
  for (const auto& ci : cart_items) {
    auto currency = currencyFromString(ci.currency);
    auto eur = cconv()->convert(Money(ci.price_cents, currency), CURRENCY_EUR);
    auto eurcents = eur.cents;
    eurcents *= ci.quantity;
    cart_eurcents_per_item.emplace(ci.item.docID().docid, eurcents);

    ++num_cart_items;
    cart_value_eurcents += eurcents;
    if (ci.checkout_step == 1) {
      gmv_eurcents_per_item.emplace(ci.item.docID().docid, eurcents);
      ++num_order_items;
      gmv_eurcents += eurcents;
    }
  }

  /* calculate gmv and ctrs per query */
  for (auto& q : queries) {
    auto slrid = extractAttr(q.attrs, "slrid");

    for (auto& i : q.items) {
      // DAWANDA HACK
      if (i.position >= 1 && i.position <= 4 && slrid.isEmpty()) {
        ++q.nads;
        q.nadclicks += i.clicked;
      }
      // EOF DAWANDA HACK

      ++q.nitems;

      if (i.clicked) {
        ++q.nclicks;

        {
          auto ci = cart_eurcents_per_item.find(i.item.docID().docid);
          if (ci != cart_eurcents_per_item.end()) {
            ++q.num_cart_items;
            q.cart_value_eurcents += ci->second;
          }
        }

        {
          auto ci = gmv_eurcents_per_item.find(i.item.docID().docid);
          if (ci != gmv_eurcents_per_item.end()) {
            ++q.num_order_items;
            q.gmv_eurcents += ci->second;
          }
        }
      }
    }
  }

  for (const auto& ci : cart_items) {
    auto& ciobj = ctx->addOutputEvent(
        ci.time,
        SHA1::compute(ctx->uuid + "~" + ci.item.docID().docid),
        "cart_items")->obj;

    ciobj.addField("time", StringUtil::toString(ci.time.unixMicros()));
    ciobj.addField("item_id", ci.item.docID().docid);
    ciobj.addField("quantity", StringUtil::toString(ci.quantity));
    ciobj.addField("price_cents", StringUtil::toString(ci.price_cents);
    ciobj.addUInt32Field("currency", (uint32_t) currencyFromString(ci.currency));
    ciobj.addField("checkout_step", StringUtil::toString(ci.checkout_step));
  }

  for (const auto& q : queries) {
    auto& qobj = ctx->addOutputEvent(
        q.time,
        SHA1::compute(ctx->uuid + "~" + q.clickid),
        "search_query")->obj;

    qobj.addField("time", StringUtil::toString(q.time.unixMicros()));
    qobj.addUInt32Field("language", (uint32_t) cm::extractLanguage(q.attrs));

    auto qstr = cm::extractQueryString(q.attrs);
    if (!qstr.isEmpty()) {
      qobj.addStringField("query_string", qstr.get());
    }

    auto slrid = cm::extractAttr(q.attrs, "slrid");
    if (!slrid.isEmpty()) {
      qobj.addField("shop_id", slrid.get());
    }

    qobj.addUInt32Field("num_result_items", q.nitems);
    qobj.addUInt32Field("num_result_items_clicked", q.nclicks);
    qobj.addUInt32Field("num_ad_impressions", q.nads);
    qobj.addUInt32Field("num_ad_clicks", q.nadclicks);
    qobj.addUInt32Field("num_cart_items", q.num_cart_items);
    qobj.addUInt32Field("cart_value_eurcents", q.cart_value_eurcents);
    qobj.addUInt32Field("num_order_items", q.num_order_items);
    qobj.addUInt32Field("gmv_eurcents", q.gmv_eurcents);

    auto pg_str = cm::extractAttr(q.attrs, "pg");
    if (!pg_str.isEmpty()) {
      qobj.addField("ab_page", pg_str.get());
    }

    auto abgrp = cm::extractABTestGroup(q.attrs);
    if (!abgrp.isEmpty()) {
      qobj.addField("ab_test_group", StringUtil::toString(abgrp.get()));
    }

    auto qcat1 = cm::extractAttr(q.attrs, "q_cat1");
    if (!qcat1.isEmpty()) {
      qobj.addField("category1", qcat1.get());
    }

    auto qcat2 = cm::extractAttr(q.attrs, "q_cat2");
    if (!qcat2.isEmpty()) {
      qobj.addField("category2", qcat2.get());
    }

    auto qcat3 = cm::extractAttr(q.attrs, "q_cat3");
    if (!qcat3.isEmpty()) {
      qobj.addField("category3", qcat3.get());
    }

    auto page_type = extractPageType(q.attrs);
    String query_type = pageTypeToString((PageType) page_type);
    auto qtype_attr = cm::extractAttr(q.attrs, "qt");
    if (!qtype_attr.isEmpty()) {
      query_type = qtype_attr.get();
    }

    qobj.addUInt32Field("device_type", (uint32_t) extractDeviceType(q.attrs));
    qobj.addUInt32Field("page_type", (uint32_t) page_type);
    qobj.addField("query_type", query_type);

    for (const auto& item : q.items) {
      qobj.addObject("result_items", [&item] (msg::DynamicMessage* ev) {
        ev->addField("position", StringUtil::toString(item.position));
        ev->addField("item_id", item.item.docID().docid);
        ev->addBoolField("clicked", item.clicked);
        ev->addBoolField("seen", item.seen);
      });
    }
  }

  for (const auto& iv : page_views) {
    auto& ivobj = ctx->addOutputEvent(
        iv.time,
        SHA1::compute(ctx->uuid + "~" + iv.clickid),
        "page_view")->obj;

    ivobj.addField("time", StringUtil::toString(iv.time.unixMicros()));
    ivobj.addField("item_id", iv.item.docID().docid);
  }

  ctx->setAttribute("num_cart_items", StringUtil::toString(num_cart_items));
  ctx->setAttribute("cart_value_eurcents", StringUtil::toString(cart_value_eurcents));
  ctx->setAttribute("num_order_items", StringUtil::toString(num_order_items));
  ctx->setAttribute("gmv_eurcents", StringUtil::toString(gmv_eurcents));
}

void SessionJoin::processSearchQueryEvent(
    const TrackedEvent& event,
    Vector<TrackedQuery>* queries) {
  TrackedQuery query;
  query.time = event.time;
  query.clickid = event.evid;

  URI::ParamList logline;
  URI::parseQueryString(event.data, &logline);
  query.fromParams(logline);

  for (auto& q : *queries) {
    if (q.clickid == query.clickid) {
      q.merge(query);
      return;
    }
  }

  queries->emplace_back(query);
}

void SessionJoin::processPageViewEvent(
    const TrackedEvent& event,
    Vector<TrackedItemVisit>* page_views) {
  TrackedItemVisit visit;
  visit.time = event.time;
  visit.clickid = event.evid;

  URI::ParamList logline;
  URI::parseQueryString(event.data, &logline);
  visit.fromParams(logline);

  for (auto& v : *page_views) {
    if (v.clickid == visit.clickid) {
      v.merge(visit);
      return;
    }
  }

  page_views->emplace_back(visit);
}

void SessionJoin::processCartItemsEvent(
    const TrackedEvent& event,
    Vector<TrackedCartItem>* cart_items) {
  URI::ParamList logline;
  URI::parseQueryString(event.data, &logline);

  auto new_cart_items = TrackedCartItem::fromParams(logline);
  for (auto& ci : new_cart_items) {
    ci.time = event.time;
  }

  for (const auto& cart_item : new_cart_items) {
    bool merged = false;

    for (auto& c : *cart_items) {
      if (c.item == cart_item.item) {
        c.merge(cart_item);
        merged = true;
        break;
      }
    }

    if (!merged) {
      cart_items->emplace_back(cart_item);
    }
  }
}

} // namespace cm

<|endoftext|>


<commit_before>/*************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2000, 2010 Oracle and/or its affiliates.
 *
 * OpenOffice.org - a multi-platform office productivity suite
 *
 * This file is part of OpenOffice.org.
 *
 * OpenOffice.org is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License version 3
 * only, as published by the Free Software Foundation.
 *
 * OpenOffice.org 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 version 3 for more details
 * (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU Lesser General Public License
 * version 3 along with OpenOffice.org.  If not, see
 * <http://www.openoffice.org/license.html>
 * for a copy of the LGPLv3 License.
 *
 ************************************************************************/

#include "oox/ppt/pptshape.hxx"
#include "oox/core/namespaces.hxx"
#include "oox/core/xmlfilterbase.hxx"
#include "tokens.hxx"

#include <com/sun/star/container/XNamed.hpp>
#include <com/sun/star/beans/XMultiPropertySet.hpp>
#include <com/sun/star/lang/XMultiServiceFactory.hpp>
#include <com/sun/star/drawing/HomogenMatrix3.hpp>
#include <com/sun/star/text/XText.hpp>
#include <basegfx/matrix/b2dhommatrix.hxx>
#include "oox/ppt/slidepersist.hxx"

using rtl::OUString;
using namespace ::oox::core;
using namespace ::com::sun::star;
using namespace ::com::sun::star::awt;
using namespace ::com::sun::star::uno;
using namespace ::com::sun::star::beans;
using namespace ::com::sun::star::frame;
using namespace ::com::sun::star::text;
using namespace ::com::sun::star::drawing;

namespace oox { namespace ppt {

PPTShape::PPTShape( const oox::ppt::ShapeLocation eShapeLocation, const sal_Char* pServiceName )
: Shape( pServiceName )
, meShapeLocation( eShapeLocation )
, mbReferenced( sal_False )
{
}

PPTShape::~PPTShape()
{
}

void PPTShape::addShape(
        const oox::core::XmlFilterBase& rFilterBase,
        const SlidePersist& rSlidePersist,
        const oox::drawingml::Theme* pTheme,
        const Reference< XShapes >& rxShapes,
        const awt::Rectangle* pShapeRect,
        ::oox::drawingml::ShapeIdMap* pShapeMap )
{
    // only placeholder from layout are being inserted
    if ( mnSubType && ( meShapeLocation == Master ) )
        return;
    try
    {
        rtl::OUString sServiceName( msServiceName );
        if( sServiceName.getLength() )
        {
            oox::drawingml::TextListStylePtr aMasterTextListStyle;
            Reference< lang::XMultiServiceFactory > xServiceFact( rFilterBase.getModel(), UNO_QUERY_THROW );
            sal_Bool bClearText = sal_False;

            if ( sServiceName != OUString::createFromAscii( "com.sun.star.drawing.GraphicObjectShape" ) )
            {
                switch( mnSubType )
                {
                    case XML_ctrTitle :
                    case XML_title :
                    {
                        const rtl::OUString sTitleShapeService( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.presentation.TitleTextShape" ) );
                        sServiceName = sTitleShapeService;
                        aMasterTextListStyle = rSlidePersist.getMasterPersist().get() ? rSlidePersist.getMasterPersist()->getTitleTextStyle() : rSlidePersist.getTitleTextStyle();
                    }
                    break;
                    case XML_obj :
                    {
                        const rtl::OUString sOutlinerShapeService( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.presentation.OutlinerShape" ) );
                        sServiceName = sOutlinerShapeService;
                        aMasterTextListStyle = rSlidePersist.getMasterPersist().get() ? rSlidePersist.getMasterPersist()->getBodyTextStyle() : rSlidePersist.getBodyTextStyle();
                    }
                    break;
                    case XML_body :
                    {
                        const rtl::OUString sNotesShapeService( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.presentation.NotesShape" ) );
                        const rtl::OUString sOutlinerShapeService( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.presentation.OutlinerShape" ) );
                        if ( rSlidePersist.isNotesPage() )
                        {
                            sServiceName = sNotesShapeService;
                            aMasterTextListStyle = rSlidePersist.getMasterPersist().get() ? rSlidePersist.getMasterPersist()->getNotesTextStyle() : rSlidePersist.getNotesTextStyle();
                        }
                        else
                        {
                            sServiceName = sOutlinerShapeService;
                            aMasterTextListStyle = rSlidePersist.getMasterPersist().get() ? rSlidePersist.getMasterPersist()->getBodyTextStyle() : rSlidePersist.getBodyTextStyle();
                        }
                    }
                    break;
                    case XML_dt :
                    {
                        const rtl::OUString sDateTimeShapeService( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.presentation.DateTimeShape" ) );
                        sServiceName = sDateTimeShapeService;
                        bClearText = sal_True;
                    }
                    break;
                    case XML_hdr :
                    {
                        const rtl::OUString sHeaderShapeService( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.presentation.HeaderShape" ) );
                        sServiceName = sHeaderShapeService;
                        bClearText = sal_True;
                    }
                    break;
                    case XML_ftr :
                    {
                        const rtl::OUString sFooterShapeService( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.presentation.FooterShape" ) );
                        sServiceName = sFooterShapeService;
                        bClearText = sal_True;
                    }
                    break;
                    case XML_sldNum :
                    {
                        const rtl::OUString sSlideNumberShapeService( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.presentation.SlideNumberShape" ) );
                        sServiceName = sSlideNumberShapeService;
                        bClearText = sal_True;
                    }
                    break;
                    case XML_sldImg :
                    {
                        const rtl::OUString sPageShapeService( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.presentation.PageShape" ) );
                        sServiceName = sPageShapeService;
                    }
                    break;

                    default:
                    break;
                }
            }
            if ( !aMasterTextListStyle.get() )
                aMasterTextListStyle = rSlidePersist.getMasterPersist().get() ? rSlidePersist.getMasterPersist()->getOtherTextStyle() : rSlidePersist.getOtherTextStyle();
            setMasterTextListStyle( aMasterTextListStyle );

            Reference< XShape > xShape( createAndInsert( rFilterBase, sServiceName, pTheme, rxShapes, pShapeRect, bClearText ) );
            if ( !rSlidePersist.isMasterPage() && rSlidePersist.getPage().is() && ( (sal_Int32)mnSubType == XML_title ) )
            {
                try
                {
                    rtl::OUString aTitleText;
                    Reference< XTextRange > xText( xShape, UNO_QUERY_THROW );
                    aTitleText = xText->getString();
                    if ( aTitleText.getLength() && ( aTitleText.getLength() < 64 ) )    // just a magic value, but we don't want to set slide names which are too long
                    {
                        Reference< container::XNamed > xName( rSlidePersist.getPage(), UNO_QUERY_THROW );
                        xName->setName( aTitleText );
                    }
                }
                catch( uno::Exception& )
                {
                }
            }
            if( pShapeMap && msId.getLength() )
            {
                (*pShapeMap)[ msId ] = shared_from_this();
            }

            // if this is a group shape, we have to add also each child shape
            Reference< XShapes > xShapes( xShape, UNO_QUERY );
            if ( xShapes.is() )
                addChildren( rFilterBase, *this, pTheme, xShapes, pShapeRect ? *pShapeRect : awt::Rectangle( maPosition.X, maPosition.Y, maSize.Width, maSize.Height ), pShapeMap );
        }
    }
    catch( const Exception&  )
    {
    }
}

void PPTShape::applyShapeReference( const oox::drawingml::Shape& rReferencedShape )
{
    Shape::applyShapeReference( rReferencedShape );
}

} }
<commit_msg>impress187: #161665# fixed problem with empty presentation object<commit_after>/*************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2000, 2010 Oracle and/or its affiliates.
 *
 * OpenOffice.org - a multi-platform office productivity suite
 *
 * This file is part of OpenOffice.org.
 *
 * OpenOffice.org is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License version 3
 * only, as published by the Free Software Foundation.
 *
 * OpenOffice.org 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 version 3 for more details
 * (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU Lesser General Public License
 * version 3 along with OpenOffice.org.  If not, see
 * <http://www.openoffice.org/license.html>
 * for a copy of the LGPLv3 License.
 *
 ************************************************************************/

#include "oox/ppt/pptshape.hxx"
#include "oox/core/namespaces.hxx"
#include "oox/core/xmlfilterbase.hxx"
#include "tokens.hxx"

#include <com/sun/star/container/XNamed.hpp>
#include <com/sun/star/beans/XMultiPropertySet.hpp>
#include <com/sun/star/lang/XMultiServiceFactory.hpp>
#include <com/sun/star/drawing/HomogenMatrix3.hpp>
#include <com/sun/star/text/XText.hpp>
#include <basegfx/matrix/b2dhommatrix.hxx>
#include "oox/ppt/slidepersist.hxx"

using rtl::OUString;
using namespace ::oox::core;
using namespace ::com::sun::star;
using namespace ::com::sun::star::awt;
using namespace ::com::sun::star::uno;
using namespace ::com::sun::star::beans;
using namespace ::com::sun::star::frame;
using namespace ::com::sun::star::text;
using namespace ::com::sun::star::drawing;

namespace oox { namespace ppt {

PPTShape::PPTShape( const oox::ppt::ShapeLocation eShapeLocation, const sal_Char* pServiceName )
: Shape( pServiceName )
, meShapeLocation( eShapeLocation )
, mbReferenced( sal_False )
{
}

PPTShape::~PPTShape()
{
}

void PPTShape::addShape(
        const oox::core::XmlFilterBase& rFilterBase,
        const SlidePersist& rSlidePersist,
        const oox::drawingml::Theme* pTheme,
        const Reference< XShapes >& rxShapes,
        const awt::Rectangle* pShapeRect,
        ::oox::drawingml::ShapeIdMap* pShapeMap )
{
    // only placeholder from layout are being inserted
    if ( mnSubType && ( meShapeLocation == Master ) )
        return;
    try
    {
        rtl::OUString sServiceName( msServiceName );
        if( sServiceName.getLength() )
        {
            oox::drawingml::TextListStylePtr aMasterTextListStyle;
            Reference< lang::XMultiServiceFactory > xServiceFact( rFilterBase.getModel(), UNO_QUERY_THROW );
            sal_Bool bClearText = sal_False;

            if ( sServiceName != OUString::createFromAscii( "com.sun.star.drawing.GraphicObjectShape" ) )
            {
                switch( mnSubType )
                {
                    case XML_ctrTitle :
                    case XML_title :
                    {
                        const rtl::OUString sTitleShapeService( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.presentation.TitleTextShape" ) );
                        sServiceName = sTitleShapeService;
                        aMasterTextListStyle = rSlidePersist.getMasterPersist().get() ? rSlidePersist.getMasterPersist()->getTitleTextStyle() : rSlidePersist.getTitleTextStyle();
                    }
                    break;
                    case XML_subTitle :
                    {
                        if ( ( meShapeLocation == Master ) || ( meShapeLocation == Layout ) )
                            sServiceName = rtl::OUString();
                    }
                    break;
                    case XML_obj :
                    {
                        const rtl::OUString sOutlinerShapeService( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.presentation.OutlinerShape" ) );
                        sServiceName = sOutlinerShapeService;
                        aMasterTextListStyle = rSlidePersist.getMasterPersist().get() ? rSlidePersist.getMasterPersist()->getBodyTextStyle() : rSlidePersist.getBodyTextStyle();
                    }
                    break;
                    case XML_body :
                    {
                        const rtl::OUString sNotesShapeService( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.presentation.NotesShape" ) );
                        const rtl::OUString sOutlinerShapeService( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.presentation.OutlinerShape" ) );
                        if ( rSlidePersist.isNotesPage() )
                        {
                            sServiceName = sNotesShapeService;
                            aMasterTextListStyle = rSlidePersist.getMasterPersist().get() ? rSlidePersist.getMasterPersist()->getNotesTextStyle() : rSlidePersist.getNotesTextStyle();
                        }
                        else
                        {
                            sServiceName = sOutlinerShapeService;
                            aMasterTextListStyle = rSlidePersist.getMasterPersist().get() ? rSlidePersist.getMasterPersist()->getBodyTextStyle() : rSlidePersist.getBodyTextStyle();
                        }
                    }
                    break;
                    case XML_dt :
                    {
                        const rtl::OUString sDateTimeShapeService( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.presentation.DateTimeShape" ) );
                        sServiceName = sDateTimeShapeService;
                        bClearText = sal_True;
                    }
                    break;
                    case XML_hdr :
                    {
                        const rtl::OUString sHeaderShapeService( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.presentation.HeaderShape" ) );
                        sServiceName = sHeaderShapeService;
                        bClearText = sal_True;
                    }
                    break;
                    case XML_ftr :
                    {
                        const rtl::OUString sFooterShapeService( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.presentation.FooterShape" ) );
                        sServiceName = sFooterShapeService;
                        bClearText = sal_True;
                    }
                    break;
                    case XML_sldNum :
                    {
                        const rtl::OUString sSlideNumberShapeService( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.presentation.SlideNumberShape" ) );
                        sServiceName = sSlideNumberShapeService;
                        bClearText = sal_True;
                    }
                    break;
                    case XML_sldImg :
                    {
                        const rtl::OUString sPageShapeService( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.presentation.PageShape" ) );
                        sServiceName = sPageShapeService;
                    }
                    break;

                    default:
                    break;
                }
            }

            if ( sServiceName.getLength() )
            {
                if ( !aMasterTextListStyle.get() )
                    aMasterTextListStyle = rSlidePersist.getMasterPersist().get() ? rSlidePersist.getMasterPersist()->getOtherTextStyle() : rSlidePersist.getOtherTextStyle();
                setMasterTextListStyle( aMasterTextListStyle );

                Reference< XShape > xShape( createAndInsert( rFilterBase, sServiceName, pTheme, rxShapes, pShapeRect, bClearText ) );
                if ( !rSlidePersist.isMasterPage() && rSlidePersist.getPage().is() && ( (sal_Int32)mnSubType == XML_title ) )
                 {
                    try
                    {
                        rtl::OUString aTitleText;
                        Reference< XTextRange > xText( xShape, UNO_QUERY_THROW );
                        aTitleText = xText->getString();
                        if ( aTitleText.getLength() && ( aTitleText.getLength() < 64 ) )    // just a magic value, but we don't want to set slide names which are too long
                        {
                            Reference< container::XNamed > xName( rSlidePersist.getPage(), UNO_QUERY_THROW );
                            xName->setName( aTitleText );
                        }
                    }
                    catch( uno::Exception& )
                    {

                    }
                }
                if( pShapeMap && msId.getLength() )
                {
                    (*pShapeMap)[ msId ] = shared_from_this();
                }

                // if this is a group shape, we have to add also each child shape
                Reference< XShapes > xShapes( xShape, UNO_QUERY );
                if ( xShapes.is() )
                    addChildren( rFilterBase, *this, pTheme, xShapes, pShapeRect ? *pShapeRect : awt::Rectangle( maPosition.X, maPosition.Y, maSize.Width, maSize.Height ), pShapeMap );
            }
        }
    }
    catch( const Exception&  )
    {
    }
}

void PPTShape::applyShapeReference( const oox::drawingml::Shape& rReferencedShape )
{
    Shape::applyShapeReference( rReferencedShape );
}

} }
<|endoftext|>


<commit_before><commit_msg>Couple of small AppCache update job mods<commit_after><|endoftext|>