<commit_before>/*=========================================================================

  Program:   Visualization Toolkit
  Module:    vtkWin32OutputWindow.cxx
  Language:  C++
  Date:      $Date$
  Version:   $Revision$

Copyright (c) 1993-2001 Ken Martin, Will Schroeder, Bill Lorensen
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:

 * Redistributions of source code must retain the above copyright notice,
   this list of conditions and the following disclaimer.

 * Redistributions in binary form must reproduce the above copyright notice,
   this list of conditions and the following disclaimer in the documentation
   and/or other materials provided with the distribution.

 * Neither name of Ken Martin, Will Schroeder, or Bill Lorensen nor the names
   of any contributors may be used to endorse or promote products derived
   from this software without specific prior written permission.

 * Modified source versions must be plainly marked as such, and must not be
   misrepresented as being the original software.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS''
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

=========================================================================*/
#include "vtkWin32OutputWindow.h"
#include "vtkObjectFactory.h"

HWND vtkWin32OutputWindow::OutputWindow = 0;

vtkWin32OutputWindow* vtkWin32OutputWindow::New()
{
  // First try to create the object from the vtkObjectFactory
  vtkObject* ret = vtkObjectFactory::CreateInstance("vtkWin32OutputWindow");
  if(ret)
    {
    return (vtkWin32OutputWindow*)ret;
    }
  // If the factory was unable to create the object, then create it here.
  return new vtkWin32OutputWindow;
}

LRESULT APIENTRY vtkWin32OutputWindow::WndProc(HWND hWnd, UINT message,
                                               WPARAM wParam,
                                               LPARAM lParam)
{
  switch (message)
    {
    case WM_SIZE:
      {
      int w = LOWORD(lParam);  // width of client area
      int h = HIWORD(lParam); // height of client area

      MoveWindow(vtkWin32OutputWindow::OutputWindow,
                 0, 0, w, h, true);
      }
      break;
    case WM_DESTROY:
      vtkWin32OutputWindow::OutputWindow = NULL;
      vtkObject::GlobalWarningDisplayOff();
      break;
    case WM_CREATE:
      break;
    }
  return DefWindowProc(hWnd, message, wParam, lParam);
}

// Display text in the window, and translate the \n to \r\n.

void vtkWin32OutputWindow::DisplayText(const char* someText)
{
  if(!someText)
    {
    return;
    }
  if(this->PromptUser)
    {
    this->PromptText(someText);
    return;
    }

  // Create a buffer big enough to hold the entire text
  char* buffer = new char[strlen(someText)+1];
  // Start at the begining
  const char* NewLinePos = someText;
  while(NewLinePos)
    {
    int len = 0;
    // Find the next new line in text
    NewLinePos = strchr(someText, '\n');
    // if no new line is found then just add the text
    if(NewLinePos == 0)
      {
      vtkWin32OutputWindow::AddText(someText);
      }
    // if a new line is found copy it to the buffer
    // and add the buffer with a control new line
    else
      {
      len = NewLinePos - someText;
      strncpy(buffer, someText, len);
      buffer[len] = 0;
      someText = NewLinePos+1;
      vtkWin32OutputWindow::AddText(buffer);
      vtkWin32OutputWindow::AddText("\r\n");
      }
    }
  delete [] buffer;
}

// Add some text to the EDIT control.

void vtkWin32OutputWindow::AddText(const char* someText)
{
  if(!Initialize()  || (strlen(someText) == 0))
    {
    return;
    }

  // move to the end of the text area
  SendMessage( vtkWin32OutputWindow::OutputWindow, EM_SETSEL,
               (WPARAM)-1, (LPARAM)-1 );
  // Append the text to the control
  SendMessage( vtkWin32OutputWindow::OutputWindow, EM_REPLACESEL,
               0, (LPARAM)someText );
}

// initialize the output window with an EDIT control and
// a container window.

int vtkWin32OutputWindow::Initialize()
{
  // check to see if it is already initialized
  if(vtkWin32OutputWindow::OutputWindow)
    {
    return 1;
    }
  // Initialized the output window

  WNDCLASS wndClass;
  // has the class been registered ?
  if (!GetClassInfo(GetModuleHandle(NULL),"vtkOutputWindow",&wndClass))
    {
    wndClass.style = CS_HREDRAW | CS_VREDRAW;
    wndClass.lpfnWndProc = vtkWin32OutputWindow::WndProc;
    wndClass.cbClsExtra = 0;
    wndClass.hInstance = GetModuleHandle(NULL);
    wndClass.hIcon = LoadIcon(NULL, IDI_APPLICATION);
    wndClass.hCursor = LoadCursor(NULL, IDC_ARROW);
    wndClass.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH);
    wndClass.lpszMenuName = NULL;
    wndClass.lpszClassName = "vtkOutputWindow";
    // vtk doesn't use these extra 4 bytes, but app writers
    // may want them, so we provide them.
    wndClass.cbWndExtra = 4;
    RegisterClass(&wndClass);
    }

  // create parent container window
  HWND win = CreateWindow(
    "vtkOutputWindow", "vtkOutputWindow",
    WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN,
    0, 0, 512, 512,
    NULL, NULL, GetModuleHandle(NULL), NULL);

  // Now create child window with text display box
  CREATESTRUCT lpParam;
  lpParam.hInstance = GetModuleHandle(NULL);
  lpParam.hMenu = NULL;
  lpParam.hwndParent = win;
  lpParam.cx = 512;
  lpParam.cy = 512;
  lpParam.x = 0;
  lpParam.y = 0;
  lpParam.style = ES_MULTILINE | ES_READONLY | WS_CHILD
    | ES_AUTOVSCROLL | ES_AUTOHSCROLL | WS_VISIBLE | WS_MAXIMIZE
    | WS_VSCROLL | WS_HSCROLL;

  lpParam.lpszName = "Output Control";
  lpParam.lpszClass = "EDIT"; // use the RICHEDIT control widget
  lpParam.dwExStyle = 0;
  // Create the EDIT window as a child of win
  vtkWin32OutputWindow::OutputWindow = CreateWindow(
    lpParam.lpszClass,  // pointer to registered class name
    "", // pointer to window name
    lpParam.style,        // window style
    lpParam.x,                // horizontal position of window
    lpParam.y,                // vertical position of window
    lpParam.cx,           // window width
    lpParam.cy,          // window height
    lpParam.hwndParent,      // handle to parent or owner window
    NULL,          // handle to menu or child-window identifier
    lpParam.hInstance,     // handle to application instance
    &lpParam        // pointer to window-creation data
    );
  const int maxsize = 5242880;

  SendMessage(vtkWin32OutputWindow::OutputWindow,
              EM_LIMITTEXT, maxsize, 0L);

  // show the top level container window
  ShowWindow(win, SW_SHOW);
  return 1;
}

void vtkWin32OutputWindow::PromptText(const char* someText)
{
  ostrstream vtkmsg;
  vtkmsg << someText << "\nPress Cancel to suppress any further messages."
         << ends;
  if (MessageBox(NULL, vtkmsg.str(), "Error",
                 MB_ICONERROR | MB_OKCANCEL) == IDCANCEL)
    {
    vtkObject::GlobalWarningDisplayOff();
    }
  vtkmsg.rdbuf()->freeze(0);
}
<commit_msg>windows ce changes<commit_after>/*=========================================================================

  Program:   Visualization Toolkit
  Module:    vtkWin32OutputWindow.cxx
  Language:  C++
  Date:      $Date$
  Version:   $Revision$

Copyright (c) 1993-2001 Ken Martin, Will Schroeder, Bill Lorensen
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:

 * Redistributions of source code must retain the above copyright notice,
   this list of conditions and the following disclaimer.

 * Redistributions in binary form must reproduce the above copyright notice,
   this list of conditions and the following disclaimer in the documentation
   and/or other materials provided with the distribution.

 * Neither name of Ken Martin, Will Schroeder, or Bill Lorensen nor the names
   of any contributors may be used to endorse or promote products derived
   from this software without specific prior written permission.

 * Modified source versions must be plainly marked as such, and must not be
   misrepresented as being the original software.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS''
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

=========================================================================*/
#include "vtkWin32OutputWindow.h"
#include "vtkObjectFactory.h"

HWND vtkWin32OutputWindow::OutputWindow = 0;

vtkWin32OutputWindow* vtkWin32OutputWindow::New()
{
  // First try to create the object from the vtkObjectFactory
  vtkObject* ret = vtkObjectFactory::CreateInstance("vtkWin32OutputWindow");
  if(ret)
    {
    return (vtkWin32OutputWindow*)ret;
    }
  // If the factory was unable to create the object, then create it here.
  return new vtkWin32OutputWindow;
}

LRESULT APIENTRY vtkWin32OutputWindow::WndProc(HWND hWnd, UINT message,
                                               WPARAM wParam,
                                               LPARAM lParam)
{
  switch (message)
    {
    case WM_SIZE:
      {
      int w = LOWORD(lParam);  // width of client area
      int h = HIWORD(lParam); // height of client area

      MoveWindow(vtkWin32OutputWindow::OutputWindow,
                 0, 0, w, h, true);
      }
      break;
    case WM_DESTROY:
      vtkWin32OutputWindow::OutputWindow = NULL;
      vtkObject::GlobalWarningDisplayOff();
      break;
    case WM_CREATE:
      break;
    }
  return DefWindowProc(hWnd, message, wParam, lParam);
}

// Display text in the window, and translate the \n to \r\n.

void vtkWin32OutputWindow::DisplayText(const char* someText)
{
  if(!someText)
    {
    return;
    }
  if(this->PromptUser)
    {
    this->PromptText(someText);
    return;
    }

  // Create a buffer big enough to hold the entire text
  char* buffer = new char[strlen(someText)+1];
  // Start at the begining
  const char* NewLinePos = someText;
  while(NewLinePos)
    {
    int len = 0;
    // Find the next new line in text
    NewLinePos = strchr(someText, '\n');
    // if no new line is found then just add the text
    if(NewLinePos == 0)
      {
      vtkWin32OutputWindow::AddText(someText);
      }
    // if a new line is found copy it to the buffer
    // and add the buffer with a control new line
    else
      {
      len = NewLinePos - someText;
      strncpy(buffer, someText, len);
      buffer[len] = 0;
      someText = NewLinePos+1;
      vtkWin32OutputWindow::AddText(buffer);
      vtkWin32OutputWindow::AddText("\r\n");
      }
    }
  delete [] buffer;
}

// Add some text to the EDIT control.

void vtkWin32OutputWindow::AddText(const char* someText)
{
  if(!Initialize()  || (strlen(someText) == 0))
    {
    return;
    }

  // move to the end of the text area
  SendMessage( vtkWin32OutputWindow::OutputWindow, EM_SETSEL,
               (WPARAM)-1, (LPARAM)-1 );
  // Append the text to the control
  SendMessage( vtkWin32OutputWindow::OutputWindow, EM_REPLACESEL,
               0, (LPARAM)someText );
}

// initialize the output window with an EDIT control and
// a container window.

int vtkWin32OutputWindow::Initialize()
{
  // check to see if it is already initialized
  if(vtkWin32OutputWindow::OutputWindow)
    {
    return 1;
    }
  // Initialized the output window

  WNDCLASS wndClass;
  // has the class been registered ?
#ifdef UNICODE
  if (!GetClassInfo(GetModuleHandle(NULL),L"vtkOutputWindow",&wndClass))
#else
  if (!GetClassInfo(GetModuleHandle(NULL),"vtkOutputWindow",&wndClass))
#endif
  {
    wndClass.style = CS_HREDRAW | CS_VREDRAW;
    wndClass.lpfnWndProc = vtkWin32OutputWindow::WndProc;
    wndClass.cbClsExtra = 0;
    wndClass.hInstance = GetModuleHandle(NULL);
//    wndClass.hIcon = LoadIcon(NULL, IDI_APPLICATION);
    wndClass.hCursor = LoadCursor(NULL, IDC_ARROW);
    wndClass.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH);
    wndClass.lpszMenuName = NULL;
#ifdef UNICODE
    wndClass.lpszClassName = L"vtkOutputWindow";
#else
    wndClass.lpszClassName = "vtkOutputWindow";
#endif
    // vtk doesn't use these extra 4 bytes, but app writers
    // may want them, so we provide them.
    wndClass.cbWndExtra = 4;
    RegisterClass(&wndClass);
    }

  // create parent container window
#ifdef _WIN32_WCE
  HWND win = CreateWindow(
    L"vtkOutputWindow", L"vtkOutputWindow",
    WS_OVERLAPPED | WS_CLIPCHILDREN,
    0, 0, 512, 512,
    NULL, NULL, GetModuleHandle(NULL), NULL);
#else
  HWND win = CreateWindow(
    "vtkOutputWindow", "vtkOutputWindow",
    WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN,
    0, 0, 512, 512,
    NULL, NULL, GetModuleHandle(NULL), NULL);
#endif

  // Now create child window with text display box
  CREATESTRUCT lpParam;
  lpParam.hInstance = GetModuleHandle(NULL);
  lpParam.hMenu = NULL;
  lpParam.hwndParent = win;
  lpParam.cx = 512;
  lpParam.cy = 512;
  lpParam.x = 0;
  lpParam.y = 0;
#ifdef _WIN32_WCE
  lpParam.style = ES_MULTILINE | ES_READONLY | WS_CHILD
    | ES_AUTOVSCROLL | ES_AUTOHSCROLL | WS_VISIBLE
    | WS_VSCROLL | WS_HSCROLL;
  lpParam.lpszName = L"Output Control";
  lpParam.lpszClass = L"EDIT"; // use the RICHEDIT control widget
#else
  lpParam.style = ES_MULTILINE | ES_READONLY | WS_CHILD
    | ES_AUTOVSCROLL | ES_AUTOHSCROLL | WS_VISIBLE | WS_MAXIMIZE
    | WS_VSCROLL | WS_HSCROLL;
  lpParam.lpszName = "Output Control";
  lpParam.lpszClass = "EDIT"; // use the RICHEDIT control widget
#endif
  lpParam.dwExStyle = 0;
  // Create the EDIT window as a child of win
#ifdef _WIN32_WCE
  vtkWin32OutputWindow::OutputWindow = CreateWindow(
    lpParam.lpszClass,  // pointer to registered class name
    L"", // pointer to window name
    lpParam.style,        // window style
    lpParam.x,                // horizontal position of window
    lpParam.y,                // vertical position of window
    lpParam.cx,           // window width
    lpParam.cy,          // window height
    lpParam.hwndParent,      // handle to parent or owner window
    NULL,          // handle to menu or child-window identifier
    lpParam.hInstance,     // handle to application instance
    &lpParam        // pointer to window-creation data
    );
#else
  vtkWin32OutputWindow::OutputWindow = CreateWindow(
    lpParam.lpszClass,  // pointer to registered class name
    "", // pointer to window name
    lpParam.style,        // window style
    lpParam.x,                // horizontal position of window
    lpParam.y,                // vertical position of window
    lpParam.cx,           // window width
    lpParam.cy,          // window height
    lpParam.hwndParent,      // handle to parent or owner window
    NULL,          // handle to menu or child-window identifier
    lpParam.hInstance,     // handle to application instance
    &lpParam        // pointer to window-creation data
    );
#endif

  const int maxsize = 5242880;

  SendMessage(vtkWin32OutputWindow::OutputWindow,
              EM_LIMITTEXT, maxsize, 0L);

  // show the top level container window
  ShowWindow(win, SW_SHOW);
  return 1;
}

void vtkWin32OutputWindow::PromptText(const char* someText)
{
  char *vtkmsg = new char [strlen(someText) + 100];
  sprintf(vtkmsg,"%s\nPress Cancel to suppress any further messages.",
          someText);
#ifdef UNICODE
        wchar_t *wmsg = new wchar_t [mbstowcs(NULL, vtkmsg, 32000)];
        mbstowcs(wmsg, vtkmsg, 32000);
    if (MessageBox(NULL, wmsg, L"Error",
                  MB_ICONERROR | MB_OKCANCEL) == IDCANCEL)
        {
      vtkObject::GlobalWarningDisplayOff();
        }
        delete [] wmsg;
#else
  if (MessageBox(NULL, vtkmsg, "Error",
                 MB_ICONERROR | MB_OKCANCEL) == IDCANCEL)
    {
    vtkObject::GlobalWarningDisplayOff();
    }
#endif
  delete [] vtkmsg;
}
<|endoftext|>


<commit_before>/******************************************************************************\
 * This example                                                               *
 * - emulates a client launching a request every 10-300ms                     *
 * - uses a CURL-backend consisting of a master and 10 workers                *
 * - runs until it is shut down by a CTRL+C signal                            *
 *                                                                            *
 *                                                                            *
 * Schematic view:                                                            *
 *                                                                            *
 *    client      |    client_job    |    curl_master    |    curl_worker     *
 *          /--------------|*|-------------\       /-------------|*|          *
 *         /---------------|*|--------------\     /                           *
 *        /----------------|*|---------------\   /                            *
 *     |*| ----------------|*|----------------|*|----------------|*|          *
 *        \________________|*|_______________/   \                            *
 *         \_______________|*|______________/     \                           *
 *          \______________|*|_____________/       \-------------|*|          *
 *                                                                            *
 *                                                                            *
 * Communication pattern:                                                     *
 *                                                                            *
 *        client_job      curl_master        curl_worker                      *
 *          |                  |                  |                           *
 *          | ----(read)-----> |                  |                           *
 *          |                  | --(forward)----> |                           *
 *          |                                     |---\                       *
 *          |                                     |   |                       *
 *          |                                     |<--/                       *
 *          | <-------------(reply)-------------- |                           *
 *          X                                                                 *
\ ******************************************************************************/

// C includes
#include <time.h>
#include <signal.h>
#include <stdlib.h>

// C++ includes
#include <string>
#include <vector>
#include <random>
#include <iostream>

// libcurl
#include <curl/curl.h>

// libcaf
#include "caf/all.hpp"

// disable some clang warnings here caused by CURL
#ifdef __clang__
# pragma clang diagnostic ignored "-Wshorten-64-to-32"
# pragma clang diagnostic ignored "-Wdisabled-macro-expansion"
# pragma clang diagnostic ignored "-Wunused-const-variable"
#endif // __clang__

using namespace caf;

using buffer_type = std::vector<char>;

using read_atom = atom_constant<atom("read")>;
using fail_atom = atom_constant<atom("fail")>;
using next_atom = atom_constant<atom("next")>;
using reply_atom = atom_constant<atom("reply")>;
using finished_atom = atom_constant<atom("finished")>;

namespace color {

// UNIX terminal color codes
constexpr char reset[]        = "\033[0m";
constexpr char reset_endl[]   = "\033[0m\n";
constexpr char black[]        = "\033[30m";
constexpr char red[]          = "\033[31m";
constexpr char green[]        = "\033[32m";
constexpr char yellow[]       = "\033[33m";
constexpr char blue[]         = "\033[34m";
constexpr char magenta[]      = "\033[35m";
constexpr char cyan[]         = "\033[36m";
constexpr char white[]        = "\033[37m";
constexpr char bold_black[]   = "\033[1m\033[30m";
constexpr char bold_red[]     = "\033[1m\033[31m";
constexpr char bold_green[]   = "\033[1m\033[32m";
constexpr char bold_yellow[]  = "\033[1m\033[33m";
constexpr char bold_blue[]    = "\033[1m\033[34m";
constexpr char bold_magenta[] = "\033[1m\033[35m";
constexpr char bold_cyan[]    = "\033[1m\033[36m";
constexpr char bold_white[]   = "\033[1m\033[37m";

} // namespace color

// number of HTTP workers
constexpr size_t num_curl_workers = 10;

// minimum delay between HTTP requests
constexpr int min_req_interval = 10;

// maximum delay between HTTP requests
constexpr int max_req_interval = 300;

// provides print utility and each base_actor has a parent
class base_actor : public event_based_actor {
protected:
  base_actor(actor parent, std::string name, std::string color_code)
      : parent_(std::move(parent)),
        name_(std::move(name)),
        color_(std::move(color_code)),
        out_(this) {
    // nop
  }

  ~base_actor();

  inline actor_ostream& print() {
    return out_ << color_ << name_ << " (id = " << id() << "): ";
  }

  void on_exit() {
    print() << "on_exit" << color::reset_endl;
  }

  actor parent_;

private:
  std::string   name_;
  std::string   color_;
  actor_ostream out_;
};

base_actor::~base_actor() {
  // avoid weak-vtables warning
}

// encapsulates an HTTP request
class client_job : public base_actor {
public:
  explicit client_job(actor parent)
      : base_actor(std::move(parent), "client_job", color::blue) {
    // nop
  }

  ~client_job();

protected:
  behavior make_behavior() override {
    print() << "init" << color::reset_endl;
    send(parent_, read_atom::value, "http://www.example.com/index.html",
         uint64_t{0}, uint64_t{4095});
    return {
      [=](reply_atom, const buffer_type& buf) {
        print() << "successfully received " << buf.size() << " bytes"
                << color::reset_endl;
        quit();
      },
      [=](fail_atom) {
        print() << "failure" << color::reset_endl;
        quit();
      }
    };
  }
};

client_job::~client_job() {
  // avoid weak-vtables warning
}

// spawns HTTP requests
class client : public base_actor {
public:

  explicit client(const actor& parent)
      : base_actor(parent, "client", color::green),
        count_(0),
        re_(rd_()),
        dist_(min_req_interval, max_req_interval) {
    // nop
  }

  ~client();

protected:
  behavior make_behavior() override {
    using std::chrono::milliseconds;
    link_to(parent_);
    print() << "init" << color::reset_endl;
    // start 'loop'
    send(this, next_atom::value);
    return (
      [=](next_atom) {
        print() << "spawn new client_job (nr. "
            << ++count_
            << ")"
            << color::reset_endl;
        // client_job will use IO
        // and should thus be spawned in a separate thread
        spawn<client_job, detached+linked>(parent_);
        // compute random delay until next job is launched
        auto delay = dist_(re_);
        delayed_send(this, milliseconds(delay), next_atom::value);
      }
    );
  }

private:
  size_t count_;
  std::random_device rd_;
  std::default_random_engine re_;
  std::uniform_int_distribution<int> dist_;
};

client::~client() {
  // avoid weak-vtables warning
}

// manages a CURL session
class curl_worker : public base_actor {
public:
  explicit curl_worker(const actor& parent)
      : base_actor(parent, "curl_worker", color::yellow),
        curl_(nullptr) {
    // nop
  }

  ~curl_worker();

protected:
  behavior make_behavior() override {
    print() << "init" << color::reset_endl;
    curl_ = curl_easy_init();
    curl_easy_setopt(curl_, CURLOPT_WRITEFUNCTION, &curl_worker::cb);
    curl_easy_setopt(curl_, CURLOPT_NOSIGNAL, 1);
    return (
      [=](read_atom, const std::string& fname, uint64_t offset, uint64_t range)
      -> message {
        print() << "read" << color::reset_endl;
        for (;;) {
          buf_.clear();
          // set URL
          curl_easy_setopt(curl_, CURLOPT_URL, fname.c_str());
          // set range
          std::ostringstream oss;
          oss << offset << "-" << range;
          curl_easy_setopt(curl_, CURLOPT_RANGE, oss.str().c_str());
          // set curl callback
          curl_easy_setopt(curl_, CURLOPT_WRITEDATA,
                           reinterpret_cast<void*>(this));
          // launch file transfer
          auto res = curl_easy_perform(curl_);
          if (res != CURLE_OK) {
            print() << "curl_easy_perform() failed: "
                    << curl_easy_strerror(res)
                    << color::reset_endl;
          } else {
            long hc = 0; // http return code
            curl_easy_getinfo(curl_, CURLINFO_RESPONSE_CODE, &hc);
            switch (hc) {
              default:
                print() << "http error: download failed with "
                        << "'HTTP RETURN CODE': "
                        << hc
                        << color::reset_endl;
                break;
              case 200: // ok
              case 206: // partial content
                print() << "received "
                        << buf_.size()
                        << " bytes with 'HTTP RETURN CODE': "
                        << hc
                        << color::reset_endl;
                // tell parent that this worker is done
                send(parent_, finished_atom::value);
                return make_message(reply_atom::value, buf_);
              case 404: // file does not exist
                print() << "http error: download failed with "
                        << "'HTTP RETURN CODE': 404 (file does "
                        << "not exist!)"
                        << color::reset_endl;
            }
          }
          // avoid 100% cpu utilization if remote side is not accessible
          std::this_thread::sleep_for(std::chrono::milliseconds(100));
        }
      }
    );
  }

  void on_exit() {
    curl_easy_cleanup(curl_);
    print() << "on_exit" << color::reset_endl;
  }

private:
  static size_t cb(void* data, size_t bsize, size_t nmemb, void* userp) {
    size_t size = bsize * nmemb;
    auto& buf = reinterpret_cast<curl_worker*>(userp)->buf_;
    auto first = reinterpret_cast<char*>(data);
    auto last = first + bsize;
    buf.insert(buf.end(), first, last);
    return size;
  }

  CURL*       curl_;
  buffer_type buf_;
};

curl_worker::~curl_worker() {
  // avoid weak-vtables warning
}

// manages {num_curl_workers} workers with a round-robin protocol
class curl_master : public base_actor {
public:
  curl_master() : base_actor(invalid_actor, "curl_master", color::magenta) {
    // nop
  }

  ~curl_master();

protected:
  behavior make_behavior() override {
    print() << "init" << color::reset_endl;
    // spawn workers
    for(size_t i = 0; i < num_curl_workers; ++i) {
      idle_worker_.push_back(spawn<curl_worker, detached+linked>(this));
    }
    auto worker_finished = [=] {
      auto sender = current_sender();
      auto last = busy_worker_.end();
      auto i = std::find(busy_worker_.begin(), last, sender);
      if (i == last) {
        return;
      }
      idle_worker_.push_back(*i);
      busy_worker_.erase(i);
      print() << "worker is done" << color::reset_endl;
    };
    print() << "spawned " << idle_worker_.size()
            << " worker(s)" << color::reset_endl;
    return {
      [=](read_atom, const std::string&, uint64_t, uint64_t) {
        print() << "received {'read'}" << color::reset_endl;
        // forward job to an idle worker
        actor worker = idle_worker_.back();
        idle_worker_.pop_back();
        busy_worker_.push_back(worker);
        forward_to(worker);
        print() << busy_worker_.size() << " active jobs" << color::reset_endl;
        if (idle_worker_.empty()) {
          // wait until at least one worker finished its job
          become (
            keep_behavior,
            [=](finished_atom) {
              worker_finished();
              unbecome();
            }
          );
        }
      },
      [=](finished_atom) {
        worker_finished();
      }
    };
  }

private:
  std::vector<actor> idle_worker_;
  std::vector<actor> busy_worker_;
};

curl_master::~curl_master() {
  // avoid weak-vtables warning
}

// signal handling for ctrl+c
namespace {
std::atomic<bool> shutdown_flag{false};
} // namespace <anonymous>

int main() {
  // random number setup
  // install signal handler
  struct sigaction act;
  act.sa_handler = [](int) { shutdown_flag = true; };
  auto set_sighandler = [&] {
    if (sigaction(SIGINT, &act, 0)) {
      std::cerr << "fatal: cannot set signal handler" << std::endl;
      abort();
    }
  };
  set_sighandler();
  // initialize CURL
  curl_global_init(CURL_GLOBAL_DEFAULT);
  { // lifetime scope of self
    scoped_actor self;
    // spawn client and curl_master
    auto master = self->spawn<curl_master, detached>();
    self->spawn<client, detached>(master);
    // poll CTRL+C flag every second
    while (! shutdown_flag) {
      std::this_thread::sleep_for(std::chrono::seconds(1));
    }
    aout(self) << color::cyan << "received CTRL+C" << color::reset_endl;
    // shutdown actors
    anon_send_exit(master, exit_reason::user_shutdown);
    // await actors
    act.sa_handler = [](int) { abort(); };
    set_sighandler();
    aout(self) << color::cyan
               << "await CURL; this may take a while "
                  "(press CTRL+C again to abort)"
               << color::reset_endl;
    self->await_all_other_actors_done();
  }
  // shutdown libcaf
  shutdown();
  // shutdown CURL
  curl_global_cleanup();
}
<commit_msg>Use stateful brokers in CURL example<commit_after>/******************************************************************************\
 * This example                                                               *
 * - emulates a client launching a request every 10-300ms                     *
 * - uses a CURL-backend consisting of a master and 10 workers                *
 * - runs until it is shut down by a CTRL+C signal                            *
 *                                                                            *
 *                                                                            *
 * Schematic view:                                                            *
 *                                                                            *
 *    client      |    client_job    |    curl_master    |    curl_worker     *
 *          /--------------|*|-------------\       /-------------|*|          *
 *         /---------------|*|--------------\     /                           *
 *        /----------------|*|---------------\   /                            *
 *     |*| ----------------|*|----------------|*|----------------|*|          *
 *        \________________|*|_______________/   \                            *
 *         \_______________|*|______________/     \                           *
 *          \______________|*|_____________/       \-------------|*|          *
 *                                                                            *
 *                                                                            *
 * Communication pattern:                                                     *
 *                                                                            *
 *        client_job      curl_master        curl_worker                      *
 *          |                  |                  |                           *
 *          | ----(read)-----> |                  |                           *
 *          |                  | --(forward)----> |                           *
 *          |                                     |---\                       *
 *          |                                     |   |                       *
 *          |                                     |<--/                       *
 *          | <-------------(reply)-------------- |                           *
 *          X                                                                 *
\ ******************************************************************************/

// C includes
#include <time.h>
#include <signal.h>
#include <stdlib.h>

// C++ includes
#include <string>
#include <vector>
#include <random>
#include <iostream>

// libcurl
#include <curl/curl.h>

// libcaf
#include "caf/all.hpp"

// disable some clang warnings here caused by CURL
#ifdef __clang__
# pragma clang diagnostic ignored "-Wshorten-64-to-32"
# pragma clang diagnostic ignored "-Wdisabled-macro-expansion"
# pragma clang diagnostic ignored "-Wunused-const-variable"
#endif // __clang__

using namespace caf;

using buffer_type = std::vector<char>;

using read_atom = atom_constant<atom("read")>;
using fail_atom = atom_constant<atom("fail")>;
using next_atom = atom_constant<atom("next")>;
using reply_atom = atom_constant<atom("reply")>;
using finished_atom = atom_constant<atom("finished")>;

namespace color {

// UNIX terminal color codes
constexpr char reset[]        = "\033[0m";
constexpr char reset_endl[]   = "\033[0m\n";
constexpr char black[]        = "\033[30m";
constexpr char red[]          = "\033[31m";
constexpr char green[]        = "\033[32m";
constexpr char yellow[]       = "\033[33m";
constexpr char blue[]         = "\033[34m";
constexpr char magenta[]      = "\033[35m";
constexpr char cyan[]         = "\033[36m";
constexpr char white[]        = "\033[37m";
constexpr char bold_black[]   = "\033[1m\033[30m";
constexpr char bold_red[]     = "\033[1m\033[31m";
constexpr char bold_green[]   = "\033[1m\033[32m";
constexpr char bold_yellow[]  = "\033[1m\033[33m";
constexpr char bold_blue[]    = "\033[1m\033[34m";
constexpr char bold_magenta[] = "\033[1m\033[35m";
constexpr char bold_cyan[]    = "\033[1m\033[36m";
constexpr char bold_white[]   = "\033[1m\033[37m";

} // namespace color

// number of HTTP workers
constexpr size_t num_curl_workers = 10;

// minimum delay between HTTP requests
constexpr int min_req_interval = 10;

// maximum delay between HTTP requests
constexpr int max_req_interval = 300;

// put everything into anonymous namespace (except main)
namespace {

// provides print utility, a name, and a parent
struct base_state {
  base_state(local_actor* thisptr) : self(thisptr) {
    // nop
  }

  actor_ostream print() {
    return aout(self) << color << name << " (id = " << self->id() << "): ";
  }

  virtual void init(actor m_parent, std::string m_name, std::string m_color) {
    parent = std::move(m_parent);
    name = std::move(m_name);
    color = std::move(m_color);
    print() << "started" << color::reset_endl;
  }

  virtual ~base_state() {
    print() << "done" << color::reset_endl;
  }

  local_actor* self;
  actor parent;
  std::string name;
  std::string color;
};

// encapsulates an HTTP request
behavior client_job(stateful_actor<base_state>* self, actor parent) {
  self->state.init(std::move(parent), "client-job", color::blue);
  self->send(self->state.parent, read_atom::value,
             "http://www.example.com/index.html",
             uint64_t{0}, uint64_t{4095});
  return {
    [=](reply_atom, const buffer_type& buf) {
      self->state.print() << "successfully received " << buf.size() << " bytes"
                          << color::reset_endl;
      self->quit();
    },
    [=](fail_atom) {
      self->state.print() << "failure" << color::reset_endl;
      self->quit();
    }
  };
}

struct client_state : base_state {
  client_state(local_actor* self)
      : base_state(self),
        count(0),
        re(rd()),
        dist(min_req_interval, max_req_interval) {
    // nop
  }

  size_t count;
  std::random_device rd;
  std::default_random_engine re;
  std::uniform_int_distribution<int> dist;
};

// spawns HTTP requests
behavior client(stateful_actor<client_state>* self, actor parent) {
  using std::chrono::milliseconds;
  self->link_to(parent);
  self->state.init(std::move(parent), "client", color::green);
  self->send(self, next_atom::value);
  return {
    [=](next_atom) {
      auto& st = self->state;
      st.print() << "spawn new client_job (nr. " << ++st.count << ")"
                 << color::reset_endl;
      // client_job will use IO
      // and should thus be spawned in a separate thread
      self->spawn<detached+linked>(client_job, st.parent);
      // compute random delay until next job is launched
      auto delay = st.dist(st.re);
      self->delayed_send(self, milliseconds(delay), next_atom::value);
    }
  };
}

struct curl_state : base_state {
  curl_state(local_actor* self) : base_state(self) {
    // nop
  }

  ~curl_state() {
    if (curl)
      curl_easy_cleanup(curl);
  }

  static size_t callback(void* data, size_t bsize, size_t nmemb, void* userp) {
    size_t size = bsize * nmemb;
    auto& buf = reinterpret_cast<curl_state*>(userp)->buf;
    auto first = reinterpret_cast<char*>(data);
    auto last = first + bsize;
    buf.insert(buf.end(), first, last);
    return size;
  }

  void init(actor m_parent, std::string m_name, std::string m_color) override {
    curl = curl_easy_init();
    if (! curl)
      throw std::runtime_error("Unable initialize CURL.");
    curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, &curl_state::callback);
    curl_easy_setopt(curl, CURLOPT_NOSIGNAL, 1);
    base_state::init(std::move(m_parent), std::move(m_name),
                     std::move(m_color));
  }

  CURL*       curl = nullptr;
  buffer_type buf;
};

// manages a CURL session
behavior curl_worker(stateful_actor<curl_state>* self, actor parent) {
  self->state.init(std::move(parent), "curl-worker", color::yellow);
  return {
    [=](read_atom, const std::string& fname, uint64_t offset, uint64_t range)
    -> message {
      auto& st = self->state;
      st.print() << "read" << color::reset_endl;
      for (;;) {
        st.buf.clear();
        // set URL
        curl_easy_setopt(st.curl, CURLOPT_URL, fname.c_str());
        // set range
        std::ostringstream oss;
        oss << offset << "-" << range;
        curl_easy_setopt(st.curl, CURLOPT_RANGE, oss.str().c_str());
        // set curl callback
        curl_easy_setopt(st.curl, CURLOPT_WRITEDATA,
                         reinterpret_cast<void*>(&st));
        // launch file transfer
        auto res = curl_easy_perform(st.curl);
        if (res != CURLE_OK) {
          st.print() << "curl_easy_perform() failed: "
                     << curl_easy_strerror(res)
                     << color::reset_endl;
        } else {
          long hc = 0; // http return code
          curl_easy_getinfo(st.curl, CURLINFO_RESPONSE_CODE, &hc);
          switch (hc) {
            default:
              st.print() << "http error: download failed with "
                         << "'HTTP RETURN CODE': "
                         << hc
                         << color::reset_endl;
              break;
            case 200: // ok
            case 206: // partial content
              st.print() << "received "
                         << st.buf.size()
                         << " bytes with 'HTTP RETURN CODE': "
                         << hc
                         << color::reset_endl;
              // tell parent that this worker is done
              self->send(st.parent, finished_atom::value);
              return make_message(reply_atom::value, std::move(st.buf));
            case 404: // file does not exist
              st.print() << "http error: download failed with "
                         << "'HTTP RETURN CODE': 404 (file does "
                         << "not exist!)"
                         << color::reset_endl;
          }
        }
        // avoid 100% cpu utilization if remote side is not accessible
        std::this_thread::sleep_for(std::chrono::milliseconds(100));
      }
    }
  };
}

struct master_state : base_state {
  master_state(local_actor* self) : base_state(self) {
    // nop
  }
  std::vector<actor> idle;
  std::vector<actor> busy;
};

behavior curl_master(stateful_actor<master_state>* self) {
  self->state.init(invalid_actor, "curl-master", color::magenta);
  // spawn workers
  for(size_t i = 0; i < num_curl_workers; ++i)
    self->state.idle.push_back(self->spawn<detached+linked>(curl_worker, self));
  auto worker_finished = [=] {
    auto sender = self->current_sender();
    auto last = self->state.busy.end();
    auto i = std::find(self->state.busy.begin(), last, sender);
    if (i == last)
      return;
    self->state.idle.push_back(*i);
    self->state.busy.erase(i);
    self->state.print() << "worker is done" << color::reset_endl;
  };
  self->state.print() << "spawned " << self->state.idle.size()
                      << " worker(s)" << color::reset_endl;
  return {
    [=](read_atom, const std::string&, uint64_t, uint64_t) {
      auto& st = self->state;
      st.print() << "received {'read'}" << color::reset_endl;
      // forward job to an idle worker
      actor worker = st.idle.back();
      st.idle.pop_back();
      st.busy.push_back(worker);
      self->forward_to(worker);
      st.print() << st.busy.size() << " active jobs" << color::reset_endl;
      if (st.idle.empty()) {
        // wait until at least one worker finished its job
        self->become (
          keep_behavior,
          [=](finished_atom) {
            worker_finished();
            self->unbecome();
          }
        );
      }
    },
    [=](finished_atom) {
      worker_finished();
    }
  };
}

// signal handling for ctrl+c
std::atomic<bool> shutdown_flag{false};

} // namespace <anonymous>

int main() {
  // random number setup
  // install signal handler
  struct sigaction act;
  act.sa_handler = [](int) { shutdown_flag = true; };
  auto set_sighandler = [&] {
    if (sigaction(SIGINT, &act, 0)) {
      std::cerr << "fatal: cannot set signal handler" << std::endl;
      abort();
    }
  };
  set_sighandler();
  // initialize CURL
  curl_global_init(CURL_GLOBAL_DEFAULT);
  { // lifetime scope of self
    scoped_actor self;
    // spawn client and curl_master
    auto master = self->spawn<detached>(curl_master);
    self->spawn<detached>(client, master);
    // poll CTRL+C flag every second
    while (! shutdown_flag)
      std::this_thread::sleep_for(std::chrono::seconds(1));
    aout(self) << color::cyan << "received CTRL+C" << color::reset_endl;
    // shutdown actors
    anon_send_exit(master, exit_reason::user_shutdown);
    // await actors
    act.sa_handler = [](int) { abort(); };
    set_sighandler();
    aout(self) << color::cyan
               << "await CURL; this may take a while "
                  "(press CTRL+C again to abort)"
               << color::reset_endl;
    self->await_all_other_actors_done();
  }
  // shutdown libcaf
  shutdown();
  // shutdown CURL
  curl_global_cleanup();
}
<|endoftext|>


<commit_before>/*
    Copyright 2010 Marco Martin <notmart@gmail.com>

    This library is free software; you can redistribute it and/or
    modify it under the terms of the GNU Library General Public
    License as published by the Free Software Foundation; either
    version 2 of the License, or (at your option) any later version.

    This library is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    Library General Public License for more details.

    You should have received a copy of the GNU Library General Public License
    along with this library; see the file COPYING.LIB.  If not, write to
    the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
    Boston, MA 02110-1301, USA.
*/

#include "pagedproxymodel.h"

#include <KDebug>

PagedProxyModel::PagedProxyModel(QObject *parent)
    : QAbstractProxyModel(parent),
      m_pageSize(16),
      m_currentPage(0)
{
}

PagedProxyModel::~PagedProxyModel()
{
}

int PagedProxyModel::totalPages()
{
    if (!sourceModel()) {
        return 0;
    }

    return sourceModel()->rowCount() / m_pageSize;
}

void PagedProxyModel::setCurrentPage(const int page)
{
    if (m_currentPage == page) {
        return;
    }

    beginResetModel();
    m_currentPage = page;
    endResetModel();
}

int PagedProxyModel::currentPage() const
{
    return m_currentPage;
}

void PagedProxyModel::setPageSize(const int size)
{
    if (m_pageSize == size) {
        return;
    }

    beginResetModel();
    m_pageSize = size;
    endResetModel();
}

int PagedProxyModel::pageSize() const
{
    return m_pageSize;
}

void PagedProxyModel::setSourceModelObject(QObject *source)
{
    QAbstractItemModel *model = qobject_cast<QAbstractItemModel *>(source);
    if (!model) {
        return;
    }
    if (sourceModel()) {
        disconnect(sourceModel(), 0, this, 0);
    }

    connect(model, SIGNAL(dataChanged(QModelIndex,QModelIndex)),
            this, SLOT(sourceDataChanged(QModelIndex,QModelIndex)));

    connect(model,  SIGNAL(rowsAboutToBeInserted(QModelIndex, int,int)),
            this, SLOT(sourceRowsAboutToBeInserted(QModelIndex,int,int)) );
    connect(model,  SIGNAL(rowsInserted(QModelIndex, int,int)),
            this, SLOT(sourceRowsInserted(QModelIndex,int,int)) );
    connect(model,  SIGNAL(rowsAboutToBeRemoved(QModelIndex, int,int)),
            this, SLOT(sourceRowsAboutToBeRemoved(QModelIndex,int,int)) );
    connect(model,  SIGNAL(rowsRemoved(QModelIndex, int,int)),
            this, SLOT(sourceRowsRemoved(QModelIndex,int,int)) );

    connect(model, SIGNAL(modelAboutToBeReset()),
               this, SIGNAL(modelAboutToBeReset()));
    connect(model, SIGNAL(modelReset()),
               this, SIGNAL(modelReset()));
    setRoleNames(model->roleNames());
    setSourceModel(model);
}

QObject *PagedProxyModel::sourceModelObject() const
{
    return sourceModel();
}

void PagedProxyModel::sourceDataChanged(const QModelIndex &from, const QModelIndex &to)
{
    emit dataChanged(mapFromSource(from), mapFromSource(to));
}

void PagedProxyModel::sourceRowsAboutToBeInserted( const QModelIndex & parentIdx, int start, int end )
{
    const int pageStart = (m_currentPage*m_pageSize);
    const int pageEnd = (m_currentPage*m_pageSize + m_pageSize);

    if (start > pageEnd || end < pageStart) {
        return;
    }

    int newStart = qMin(m_pageSize, qMax(0, start - pageStart));
    int newEnd = qMin(m_pageSize, qMax(0, end - pageStart));

    beginInsertRows(parentIdx, newStart, newEnd );

}

void PagedProxyModel::sourceRowsInserted( const QModelIndex& parentIdx, int start, int end )
{
    Q_UNUSED( parentIdx );
    Q_UNUSED( start );
    Q_UNUSED( end );
    endInsertRows();
}

void PagedProxyModel::sourceRowsAboutToBeRemoved( const QModelIndex & parentIdx, int start, int end )
{
    const int pageStart = (m_currentPage*m_pageSize);
    const int pageEnd = (m_currentPage*m_pageSize + m_pageSize);

    if (start > pageEnd || end < pageStart) {
        return;
    }

    int newStart = qMin(m_pageSize, qMax(0, start - pageStart));
    int newEnd = qMin(m_pageSize, qMax(0, end - pageStart));

    beginRemoveRows(parentIdx, newStart, newEnd );
}

void PagedProxyModel::sourceRowsRemoved( const QModelIndex& parentIdx, int start, int end )
{
    Q_UNUSED( parentIdx );
    Q_UNUSED( start );
    Q_UNUSED( end );
    endRemoveRows();
}

int PagedProxyModel::rowCount(const QModelIndex &parent) const
{
    if (!sourceModel()) {
        return 0;
    }

    return qMin(m_pageSize, (sourceModel()->rowCount(parent)-m_currentPage*m_pageSize));
}

QVariant PagedProxyModel::data(const QModelIndex &index, int role) const
{
    if (!sourceModel()) {
        return QVariant();
    }

    return sourceModel()->data(PagedProxyModel::index(index.row()+ (m_currentPage*m_pageSize), index.column(), QModelIndex()), role);
}

QModelIndex PagedProxyModel::index(int row, int column, const QModelIndex &parent) const
{
    if (!sourceModel()) {
        return QModelIndex();
    }

    return sourceModel()->index(row, column, parent);
}

QModelIndex PagedProxyModel::parent(const QModelIndex &index) const
{
    return QModelIndex();
}

QModelIndex PagedProxyModel::mapFromSource(const QModelIndex &sourceIndex) const
{
    if (!sourceModel()) {
        return QModelIndex();
    }

    return sourceModel()->index(sourceIndex.row() - (m_currentPage*m_pageSize), sourceIndex.column(), QModelIndex());
}

QModelIndex PagedProxyModel::mapToSource(const QModelIndex &proxyIndex) const
{
    if (!sourceModel()) {
        return QModelIndex();
    }

    return sourceModel()->index(proxyIndex.row() + (m_currentPage*m_pageSize), proxyIndex.column(), QModelIndex());
}

int PagedProxyModel::columnCount(const QModelIndex &index) const
{
    if (!sourceModel()) {
        return 0;
    }
    return sourceModel()->columnCount(index);
}

#include "pagedproxymodel.moc"
<commit_msg>reinsert items if they can be taken from next pages<commit_after>/*
    Copyright 2010 Marco Martin <notmart@gmail.com>

    This library is free software; you can redistribute it and/or
    modify it under the terms of the GNU Library General Public
    License as published by the Free Software Foundation; either
    version 2 of the License, or (at your option) any later version.

    This library is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    Library General Public License for more details.

    You should have received a copy of the GNU Library General Public License
    along with this library; see the file COPYING.LIB.  If not, write to
    the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
    Boston, MA 02110-1301, USA.
*/

#include "pagedproxymodel.h"

#include <KDebug>

PagedProxyModel::PagedProxyModel(QObject *parent)
    : QAbstractProxyModel(parent),
      m_pageSize(16),
      m_currentPage(0)
{
}

PagedProxyModel::~PagedProxyModel()
{
}

int PagedProxyModel::totalPages()
{
    if (!sourceModel()) {
        return 0;
    }

    return sourceModel()->rowCount() / m_pageSize;
}

void PagedProxyModel::setCurrentPage(const int page)
{
    if (m_currentPage == page) {
        return;
    }

    beginResetModel();
    m_currentPage = page;
    endResetModel();
}

int PagedProxyModel::currentPage() const
{
    return m_currentPage;
}

void PagedProxyModel::setPageSize(const int size)
{
    if (m_pageSize == size) {
        return;
    }

    beginResetModel();
    m_pageSize = size;
    endResetModel();
}

int PagedProxyModel::pageSize() const
{
    return m_pageSize;
}

void PagedProxyModel::setSourceModelObject(QObject *source)
{
    QAbstractItemModel *model = qobject_cast<QAbstractItemModel *>(source);
    if (!model) {
        return;
    }
    if (sourceModel()) {
        disconnect(sourceModel(), 0, this, 0);
    }

    connect(model, SIGNAL(dataChanged(QModelIndex,QModelIndex)),
            this, SLOT(sourceDataChanged(QModelIndex,QModelIndex)));

    connect(model,  SIGNAL(rowsAboutToBeInserted(QModelIndex, int,int)),
            this, SLOT(sourceRowsAboutToBeInserted(QModelIndex,int,int)) );
    connect(model,  SIGNAL(rowsInserted(QModelIndex, int,int)),
            this, SLOT(sourceRowsInserted(QModelIndex,int,int)) );
    connect(model,  SIGNAL(rowsAboutToBeRemoved(QModelIndex, int,int)),
            this, SLOT(sourceRowsAboutToBeRemoved(QModelIndex,int,int)) );
    connect(model,  SIGNAL(rowsRemoved(QModelIndex, int,int)),
            this, SLOT(sourceRowsRemoved(QModelIndex,int,int)) );

    connect(model, SIGNAL(modelAboutToBeReset()),
               this, SIGNAL(modelAboutToBeReset()));
    connect(model, SIGNAL(modelReset()),
               this, SIGNAL(modelReset()));
    setRoleNames(model->roleNames());
    setSourceModel(model);
}

QObject *PagedProxyModel::sourceModelObject() const
{
    return sourceModel();
}

void PagedProxyModel::sourceDataChanged(const QModelIndex &from, const QModelIndex &to)
{
    emit dataChanged(mapFromSource(from), mapFromSource(to));
}

void PagedProxyModel::sourceRowsAboutToBeInserted( const QModelIndex & parentIdx, int start, int end )
{
    const int pageStart = (m_currentPage*m_pageSize);
    const int pageEnd = (m_currentPage*m_pageSize + m_pageSize);

    //if we insert a row before the page, we have ro rewrite the whole page anyways
    if (start <= pageStart) {
        beginResetModel();
        return;
    } else if (start > pageEnd) {
        return;
    //start > pageStart
    //some old items will go because they overflow the page size
    } else if (end - start > m_pageSize - rowCount()) {
        beginRemoveRows(parentIdx, m_pageSize, (end - start - rowCount()));
    }

    int newStart = qMin(m_pageSize, qMax(0, start - pageStart));
    int newEnd = qMin(m_pageSize, qMax(0, end - pageStart));

    beginInsertRows(parentIdx, newStart, newEnd );
}

void PagedProxyModel::sourceRowsInserted( const QModelIndex& parentIdx, int start, int end )
{
    Q_UNUSED( parentIdx );
    Q_UNUSED( end );
    const int pageStart = (m_currentPage*m_pageSize);
    if (start <= pageStart) {
        endResetModel();
    } else {
        endInsertRows();
    }
    endRemoveRows();
}

void PagedProxyModel::sourceRowsAboutToBeRemoved( const QModelIndex & parentIdx, int start, int end )
{
    const int pageStart = (m_currentPage*m_pageSize);
    const int pageEnd = (m_currentPage*m_pageSize + m_pageSize);

    //if we remove a row before the page, we have to rewrite the whole page anyways
    if (start <= pageStart) {
        beginResetModel();
        return;
    } else if (start > pageEnd) {
        return;
    }

    int newStart = qMin(m_pageSize, qMax(0, start - pageStart));
    int newEnd = qMin(m_pageSize, qMax(0, end - pageStart));

    beginRemoveRows(parentIdx, newStart, newEnd );

     //how many rows remain that can be put back i the page?
    if (sourceModel()->rowCount() - (end - start) - pageStart > 0) {
        beginInsertRows(parentIdx, newStart,
                        qMin(newEnd,
                         (sourceModel()->rowCount() - (end - start) - pageStart)));
    }
}

void PagedProxyModel::sourceRowsRemoved( const QModelIndex& parentIdx, int start, int end )
{
    Q_UNUSED( parentIdx );
    Q_UNUSED( end );
    const int pageStart = (m_currentPage*m_pageSize);
    if (start <= pageStart) {
        endResetModel();
    } else {
        endRemoveRows();
        endInsertRows();
    }
}

int PagedProxyModel::rowCount(const QModelIndex &parent) const
{
    if (!sourceModel()) {
        return 0;
    }

    return qMin(m_pageSize, (sourceModel()->rowCount(parent)-m_currentPage*m_pageSize));
}

QVariant PagedProxyModel::data(const QModelIndex &index, int role) const
{
    if (!sourceModel()) {
        return QVariant();
    }

    return sourceModel()->data(PagedProxyModel::index(index.row()+ (m_currentPage*m_pageSize), index.column(), QModelIndex()), role);
}

QModelIndex PagedProxyModel::index(int row, int column, const QModelIndex &parent) const
{
    if (!sourceModel()) {
        return QModelIndex();
    }

    return sourceModel()->index(row, column, parent);
}

QModelIndex PagedProxyModel::parent(const QModelIndex &index) const
{
    return QModelIndex();
}

QModelIndex PagedProxyModel::mapFromSource(const QModelIndex &sourceIndex) const
{
    if (!sourceModel()) {
        return QModelIndex();
    }

    return sourceModel()->index(sourceIndex.row() - (m_currentPage*m_pageSize), sourceIndex.column(), QModelIndex());
}

QModelIndex PagedProxyModel::mapToSource(const QModelIndex &proxyIndex) const
{
    if (!sourceModel()) {
        return QModelIndex();
    }

    return sourceModel()->index(proxyIndex.row() + (m_currentPage*m_pageSize), proxyIndex.column(), QModelIndex());
}

int PagedProxyModel::columnCount(const QModelIndex &index) const
{
    if (!sourceModel()) {
        return 0;
    }
    return sourceModel()->columnCount(index);
}

#include "pagedproxymodel.moc"
<|endoftext|>


<commit_before>/**
 * licensed to the apache software foundation (asf) under one
 * or more contributor license agreements.  see the notice file
 * distributed with this work for additional information
 * regarding copyright ownership.  the asf licenses this file
 * to you under the apache license, version 2.0 (the
 * "license"); you may not use this file except in compliance
 * with the license.  you may obtain a copy of the license at
 *
 *     http://www.apache.org/licenses/license-2.0
 *
 * unless required by applicable law or agreed to in writing, software
 * distributed under the license is distributed on an "as is" basis,
 * without warranties or conditions of any kind, either express or implied.
 * see the license for the specific language governing permissions and
 * limitations under the license.
 */

#include <string>

#if defined(__linux__) || defined(__sun__)
#include "monitoring/proc_resource_collector.hpp"
#endif

#include "monitoring/process_resource_collector.hpp"

using std::string;

namespace mesos {
namespace internal {
namespace monitoring {

ProcessResourceCollector* ProcessResourceCollector::create(const string& root_pid)
{
#if defined(__linux__) || defined(__sun__)
  return new ProcResourceCollector(root_pid);
#else
  return NULL;
#endif
}

} // namespace monitoring {
} // namespace internal {
} // namespace mesos {
<commit_msg>Fixing ProcResourceMonitor to only generate on Linux.<commit_after>/**
 * licensed to the apache software foundation (asf) under one
 * or more contributor license agreements.  see the notice file
 * distributed with this work for additional information
 * regarding copyright ownership.  the asf licenses this file
 * to you under the apache license, version 2.0 (the
 * "license"); you may not use this file except in compliance
 * with the license.  you may obtain a copy of the license at
 *
 *     http://www.apache.org/licenses/license-2.0
 *
 * unless required by applicable law or agreed to in writing, software
 * distributed under the license is distributed on an "as is" basis,
 * without warranties or conditions of any kind, either express or implied.
 * see the license for the specific language governing permissions and
 * limitations under the license.
 */

#include <string>

#if defined(__linux__) || defined(__sun__)
#include "monitoring/proc_resource_collector.hpp"
#endif

#include "monitoring/process_resource_collector.hpp"

using std::string;

namespace mesos {
namespace internal {
namespace monitoring {

ProcessResourceCollector* ProcessResourceCollector::create(const string& root_pid)
{
#ifdef __linux__
  return new ProcResourceCollector(root_pid);
#else
  return NULL;
#endif
}

} // namespace monitoring {
} // namespace internal {
} // namespace mesos {
<|endoftext|>


<commit_before>/**************************************************************************
**
** This file is part of Qt Creator
**
** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
**
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** Commercial Usage
**
** Licensees holding valid Qt Commercial licenses may use this file in
** accordance with the Qt Commercial License Agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Nokia.
**
** GNU Lesser General Public License Usage
**
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** If you are unsure which license is appropriate for your use, please
** contact the sales department at http://qt.nokia.com/contact.
**
**************************************************************************/

#include "completionsettings.h"

#include <QtCore/QSettings>

static const char * const groupPostfix = "Completion";
static const char * const caseSensitivityKey = "CaseSensitivity";
static const char * const autoInsertBracesKey = "AutoInsertBraces";
static const char * const partiallyCompleteKey = "PartiallyComplete";
static const char * const spaceAfterFunctionNameKey = "SpaceAfterFunctionName";

using namespace TextEditor;

CompletionSettings::CompletionSettings()
    : m_caseSensitivity(FirstLetterCaseSensitive)
    , m_autoInsertBrackets(true)
    , m_partiallyComplete(true)
    , m_spaceAfterFunctionName(false)
{
}

void CompletionSettings::toSettings(const QString &category, QSettings *s) const
{
    QString group = QLatin1String(groupPostfix);
    if (!category.isEmpty())
        group.insert(0, category);

    s->beginGroup(group);
    s->setValue(QLatin1String(caseSensitivityKey), (int) m_caseSensitivity);
    s->setValue(QLatin1String(autoInsertBracesKey), m_autoInsertBrackets);
    s->setValue(QLatin1String(partiallyCompleteKey), m_partiallyComplete);
    s->setValue(QLatin1String(spaceAfterFunctionNameKey), m_spaceAfterFunctionName);
    s->endGroup();
}

void CompletionSettings::fromSettings(const QString &category, const QSettings *s)
{
    QString group = QLatin1String(groupPostfix);
    if (!category.isEmpty())
        group.insert(0, category);
    group += QLatin1Char('/');

    *this = CompletionSettings(); // Assign defaults

    m_caseSensitivity = (CaseSensitivity) s->value(group + QLatin1String(caseSensitivityKey), m_caseSensitivity).toInt();
    m_autoInsertBrackets = s->value(group + QLatin1String(autoInsertBracesKey), m_autoInsertBrackets).toBool();
    m_partiallyComplete = s->value(group + QLatin1String(partiallyCompleteKey), m_partiallyComplete).toBool();
    m_spaceAfterFunctionName = s->value(group + QLatin1String(spaceAfterFunctionNameKey), m_spaceAfterFunctionName).toBool();
}

bool CompletionSettings::equals(const CompletionSettings &cs) const
{
    return m_caseSensitivity == cs.m_caseSensitivity
        && m_autoInsertBrackets == cs.m_autoInsertBrackets
        && m_partiallyComplete == cs.m_partiallyComplete
        && m_spaceAfterFunctionName == cs.m_spaceAfterFunctionName
        ;
}
<commit_msg>Switched completion to be case-insensitive by default<commit_after>/**************************************************************************
**
** This file is part of Qt Creator
**
** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
**
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** Commercial Usage
**
** Licensees holding valid Qt Commercial licenses may use this file in
** accordance with the Qt Commercial License Agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Nokia.
**
** GNU Lesser General Public License Usage
**
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** If you are unsure which license is appropriate for your use, please
** contact the sales department at http://qt.nokia.com/contact.
**
**************************************************************************/

#include "completionsettings.h"

#include <QtCore/QSettings>

static const char * const groupPostfix = "Completion";
static const char * const caseSensitivityKey = "CaseSensitivity";
static const char * const autoInsertBracesKey = "AutoInsertBraces";
static const char * const partiallyCompleteKey = "PartiallyComplete";
static const char * const spaceAfterFunctionNameKey = "SpaceAfterFunctionName";

using namespace TextEditor;

CompletionSettings::CompletionSettings()
    : m_caseSensitivity(CaseInsensitive)
    , m_autoInsertBrackets(true)
    , m_partiallyComplete(true)
    , m_spaceAfterFunctionName(false)
{
}

void CompletionSettings::toSettings(const QString &category, QSettings *s) const
{
    QString group = QLatin1String(groupPostfix);
    if (!category.isEmpty())
        group.insert(0, category);

    s->beginGroup(group);
    s->setValue(QLatin1String(caseSensitivityKey), (int) m_caseSensitivity);
    s->setValue(QLatin1String(autoInsertBracesKey), m_autoInsertBrackets);
    s->setValue(QLatin1String(partiallyCompleteKey), m_partiallyComplete);
    s->setValue(QLatin1String(spaceAfterFunctionNameKey), m_spaceAfterFunctionName);
    s->endGroup();
}

void CompletionSettings::fromSettings(const QString &category, const QSettings *s)
{
    QString group = QLatin1String(groupPostfix);
    if (!category.isEmpty())
        group.insert(0, category);
    group += QLatin1Char('/');

    *this = CompletionSettings(); // Assign defaults

    m_caseSensitivity = (CaseSensitivity) s->value(group + QLatin1String(caseSensitivityKey), m_caseSensitivity).toInt();
    m_autoInsertBrackets = s->value(group + QLatin1String(autoInsertBracesKey), m_autoInsertBrackets).toBool();
    m_partiallyComplete = s->value(group + QLatin1String(partiallyCompleteKey), m_partiallyComplete).toBool();
    m_spaceAfterFunctionName = s->value(group + QLatin1String(spaceAfterFunctionNameKey), m_spaceAfterFunctionName).toBool();
}

bool CompletionSettings::equals(const CompletionSettings &cs) const
{
    return m_caseSensitivity == cs.m_caseSensitivity
        && m_autoInsertBrackets == cs.m_autoInsertBrackets
        && m_partiallyComplete == cs.m_partiallyComplete
        && m_spaceAfterFunctionName == cs.m_spaceAfterFunctionName
        ;
}
<|endoftext|>


<commit_before>#include <iomanip>
#include <iostream>

class Horario {
  public:
    Horario( int hora, int minuto, int segundo );
    void setHorario( int hora, int minuto, int segundo );
    void printUniversal();
    void printStandard();

  private:
    int hora, minuto, segundo;
};

Horario::Horario( int hora, int minuto, int segundo ) {
    std::cout << "Criação do Horario" << '\n';

    setHorario( hora, minuto, segundo );
}

void Horario::setHorario( int hora, int minuto, int segundo ) {
    this->hora = ( hora >= 0 && hora < 24 ) ? hora : 0;
    this->minuto = ( minuto >= 0 && minuto < 60 ) ? minuto : 0;
    this->segundo = ( segundo >= 0 && segundo < 60 ) ? segundo : 0;
}

void Horario::printUniversal() {
    std::cout << std::setfill( '0' ) << std::setw( 2 ) << hora << " " << minuto << " " << segundo
              << '\n';
}

void Horario::printStandard() {
    std::cout << ( ( hora >= 0 && hora < 12 ) ? hora : ( hora % 12 ) ) << ":" << minuto << ":"
              << segundo << '\n';
}

int main() {
    Horario porDoSol( 10, 1, 0 );

    porDoSol.setHorario( 18, 0, 0 );

    porDoSol.printStandard();

    return 0;
}
<commit_msg>Implementação do AM/PM<commit_after>#include <iomanip>
#include <iostream>

class Horario {
  public:
    Horario( int hora, int minuto, int segundo );
    void setHorario( int hora, int minuto, int segundo );
    void printUniversal();
    void printStandard();

  private:
    int hora, minuto, segundo;
};

Horario::Horario( int hora, int minuto, int segundo ) {
    std::cout << "Criação do Horario" << '\n';

    setHorario( hora, minuto, segundo );
}

void Horario::setHorario( int hora, int minuto, int segundo ) {
    this->hora = ( hora >= 0 && hora < 24 ) ? hora : 0;
    this->minuto = ( minuto >= 0 && minuto < 60 ) ? minuto : 0;
    this->segundo = ( segundo >= 0 && segundo < 60 ) ? segundo : 0;
}

void Horario::printUniversal() {
    std::cout << std::setfill( '0' ) << std::setw( 2 ) << hora << " " << minuto << " " << segundo
              << '\n';
}

void Horario::printStandard() {
    std::cout << ( ( hora >= 0 && hora < 12 ) ? hora : ( hora % 12 ) ) << ":" << minuto << ":"
              << segundo << " " << ( ( hora < 12 ) ? "AM" : "PM" ) << '\n';
}

int main() {
    Horario porDoSol( 10, 1, 0 );

    porDoSol.setHorario( 12, 0, 0 );

    porDoSol.printStandard();

    return 0;
}
<|endoftext|>


<commit_before>#define DEBUG 0
/**
 * File    : H.cpp
 * Author  : Kazune Takahashi
 * Created : 2019/12/30 18:11:35
 * Powered by Visual Studio Code
 */
#include <iostream>
#include <iomanip>
#include <algorithm>
#include <vector>
#include <string>
#include <complex>
#include <tuple>
#include <queue>
#include <stack>
#include <map>
#include <set>
#include <unordered_map>
#include <unordered_set>
#include <bitset>
#include <functional>
#include <random>
#include <chrono>
#include <cctype>
#include <cassert>
#include <cmath>
#include <cstdio>
#include <cstdlib>
// ----- boost -----
#include <boost/rational.hpp>
// ----- using directives and manipulations -----
using boost::rational;
using namespace std;
using ll = long long;
// ----- constexpr for Mint and Combination -----
constexpr ll MOD{1000000007LL};
// constexpr ll MOD{998244353LL}; // be careful
constexpr ll MAX_SIZE{3000010LL};
// constexpr ll MAX_SIZE{30000010LL}; // if 10^7 is needed
// ----- ch_max and ch_min -----
template <typename T>
void ch_max(T &left, T right)
{
  if (left < right)
  {
    left = right;
  }
}
template <typename T>
void ch_min(T &left, T right)
{
  if (left > right)
  {
    left = right;
  }
}
// ----- Mint -----
template <ll MOD = MOD>
class Mint
{
public:
  ll x;
  Mint() : x{0LL} {}
  Mint(ll x) : x{x % MOD} {}
  Mint operator-() const { return x ? MOD - x : 0; }
  Mint &operator+=(const Mint &a)
  {
    if ((x += a.x) >= MOD)
    {
      x -= MOD;
    }
    return *this;
  }
  Mint &operator-=(const Mint &a) { return *this += -a; }
  Mint &operator*=(const Mint &a)
  {
    (x *= a.x) %= MOD;
    return *this;
  }
  Mint &operator/=(const Mint &a)
  {
    Mint b{a};
    return *this *= b.power(MOD - 2);
  }
  Mint operator+(const Mint &a) const { return Mint(*this) += a; }
  Mint operator-(const Mint &a) const { return Mint(*this) -= a; }
  Mint operator*(const Mint &a) const { return Mint(*this) *= a; }
  Mint operator/(const Mint &a) const { return Mint(*this) /= a; }
  bool operator<(const Mint &a) const { return x < a.x; }
  bool operator<=(const Mint &a) const { return x <= a.x; }
  bool operator>(const Mint &a) const { return x > a.x; }
  bool operator>=(const Mint &a) const { return x >= a.x; }
  bool operator==(const Mint &a) const { return x == a.x; }
  bool operator!=(const Mint &a) const { return !(*this == a); }
  const Mint power(ll N)
  {
    if (N == 0)
    {
      return 1;
    }
    else if (N % 2 == 1)
    {
      return *this * power(N - 1);
    }
    else
    {
      Mint half = power(N / 2);
      return half * half;
    }
  }
};
template <ll MOD>
Mint<MOD> operator+(ll lhs, const Mint<MOD> &rhs)
{
  return rhs + lhs;
}
template <ll MOD>
Mint<MOD> operator-(ll lhs, const Mint<MOD> &rhs)
{
  return -rhs + lhs;
}
template <ll MOD>
Mint<MOD> operator*(ll lhs, const Mint<MOD> &rhs)
{
  return rhs * lhs;
}
template <ll MOD>
Mint<MOD> operator/(ll lhs, const Mint<MOD> &rhs)
{
  return Mint<MOD>{lhs} / rhs;
}
template <ll MOD>
istream &operator>>(istream &stream, Mint<MOD> &a)
{
  return stream >> a.x;
}
template <ll MOD>
ostream &operator<<(ostream &stream, const Mint<MOD> &a)
{
  return stream << a.x;
}
// ----- Combination -----
template <ll MOD = MOD, ll MAX_SIZE = MAX_SIZE>
class Combination
{
public:
  vector<Mint<MOD>> inv, fact, factinv;
  Combination() : inv(MAX_SIZE), fact(MAX_SIZE), factinv(MAX_SIZE)
  {
    inv[1] = 1;
    for (auto i = 2LL; i < MAX_SIZE; i++)
    {
      inv[i] = (-inv[MOD % i]) * (MOD / i);
    }
    fact[0] = factinv[0] = 1;
    for (auto i = 1LL; i < MAX_SIZE; i++)
    {
      fact[i] = Mint<MOD>(i) * fact[i - 1];
      factinv[i] = inv[i] * factinv[i - 1];
    }
  }
  Mint<MOD> operator()(int n, int k)
  {
    if (n >= 0 && k >= 0 && n - k >= 0)
    {
      return fact[n] * factinv[k] * factinv[n - k];
    }
    return 0;
  }
  Mint<MOD> catalan(int x, int y)
  {
    return (*this)(x + y, y) - (*this)(x + y, y - 1);
  }
};
// ----- for C++14 -----
using mint = Mint<MOD>;
using combination = Combination<MOD, MAX_SIZE>;
ll gcd(ll x, ll y) { return y ? gcd(y, x % y) : x; }
// ----- frequently used constexpr -----
// constexpr double epsilon{1e-10};
// constexpr ll infty{1000000000000000LL};
// constexpr int dx[4] = {1, 0, -1, 0};
// constexpr int dy[4] = {0, 1, 0, -1};
// ----- Yes() and No() -----
void Yes()
{
  cout << "Yes" << endl;
  exit(0);
}
void No()
{
  cout << "No" << endl;
  exit(0);
}

// ----- PrimeNums -----

class PrimeNums
{
  static constexpr ll MAX_SIZE{1000010LL};
  ll N;
  vector<bool> isprime;
  vector<int> prime_nums;

public:
  PrimeNums(ll N = MAX_SIZE) : N{N}, isprime(N, true), prime_nums{}
  {
    isprime[0] = isprime[1] = false;
    for (auto i = 2; i < N; i++)
    {
      if (isprime[i])
      {
        prime_nums.push_back(i);
        for (auto j = 2 * i; j < N; j += i)
        {
          isprime[j] = false;
        }
      }
    }
  }

  bool is_prime(long long x)
  { // 2 \leq x \leq MAX_SIZE^2
    if (x < N)
    {
      return isprime[x];
    }
    for (auto e : prime_nums)
    {
      if (x % e == 0)
        return false;
    }
    return true;
  }

  vector<int> const &primes() const
  {
    return prime_nums;
  }
};

// ----- main() -----
class Solve
{
  int H, W;
  vector<string> S;
  PrimeNums pn;

public:
  Solve(int H, int W, vector<string> const &S) : H{H}, W{W}, S(S), pn{} {}

  int calc()
  {
    int ans{0};
    for (auto i = 0; i < H; i++)
    {
      ans += calc(S[i]);
    }
    return ans;
  };

private:
  int calc(string const &T)
  {
    if (is_zero(T))
    {
      return 0;
    }
    auto V{make_vec(T)};
    if (is_one(V))
    {
      return 1;
    }
    if (is_two(V))
    {
      return 2;
    }
    return 3;
  }

  bool is_zero(string const &T)
  {
    for (auto x : T)
    {
      if (x == '.')
      {
        return false;
      }
    }
    return true;
  }

  vector<int> make_vec(string const &T)
  {
    int first{-1};
    vector<int> V;
    for (auto i = 0; i < W; i++)
    {
      if (T[i] == '.')
      {
        if (first == -1)
        {
          first = i;
        }
        V.push_back(i - first);
      }
    }
    return V;
  }

  bool is_one(vector<int> const &V)
  {
    if (V.size() < size_t{2})
    {
      return true;
    }
    assert(V[0] == 0);
    int g{V[1]};
    for (auto it = V.begin() + 1; it != V.end(); it++)
    {
      g = gcd(g, *it);
    }
    for (auto i = 0; i < 20; i++)
    {
      if (g == 1 << i)
      {
        return false;
      }
    }
    return true;
  }

  bool is_two(vector<int> const &V)
  {
    int X{static_cast<int>(V.size())};
    if (X <= 1)
    {
      assert(false);
      return false;
    }
    if (X == 2)
    {
      return true;
    }
    if (X == 3)
    {
      assert(false);
    }
    for (auto it = pn.primes().begin() + 1; it != pn.primes().end(); it++)
    {
      int p{static_cast<int>(*it)};
      if (W / p < X / 2)
      {
        return false;
      }
      vector<int> M;
      M.push_back(0);
      for (auto i = 1; i < X; i++)
      {
        if (V[i] % p == 0)
        {
          continue;
        }
        M.push_back(V[i]);
        break;
      }
      for (auto m : M)
      {
        int first{-1};
        vector<int> W;
        for (auto x : V)
        {
          if ((x - m) % p == 0)
          {
            continue;
          }
          if (first == -1)
          {
            first = x;
          }
          W.push_back(x - first);
        }
        if (is_one(W))
        {
          return true;
        }
      }
    }
    assert(false);
    return false;
  }
};

int main()
{
  int H, W;
  cin >> H >> W;
  vector<string> S(H);
  for (auto i = 0; i < H; i++)
  {
    cin >> S[i];
  }
  Solve solve(H, W, S);
  cout << solve.calc() << endl;
}
<commit_msg>tried H.cpp to 'H'<commit_after>#define DEBUG 0
/**
 * File    : H.cpp
 * Author  : Kazune Takahashi
 * Created : 2019/12/30 18:11:35
 * Powered by Visual Studio Code
 */
#include <iostream>
#include <iomanip>
#include <algorithm>
#include <vector>
#include <string>
#include <complex>
#include <tuple>
#include <queue>
#include <stack>
#include <map>
#include <set>
#include <unordered_map>
#include <unordered_set>
#include <bitset>
#include <functional>
#include <random>
#include <chrono>
#include <cctype>
#include <cassert>
#include <cmath>
#include <cstdio>
#include <cstdlib>
// ----- boost -----
#include <boost/rational.hpp>
// ----- using directives and manipulations -----
using boost::rational;
using namespace std;
using ll = long long;
// ----- constexpr for Mint and Combination -----
constexpr ll MOD{1000000007LL};
// constexpr ll MOD{998244353LL}; // be careful
constexpr ll MAX_SIZE{3000010LL};
// constexpr ll MAX_SIZE{30000010LL}; // if 10^7 is needed
// ----- ch_max and ch_min -----
template <typename T>
void ch_max(T &left, T right)
{
  if (left < right)
  {
    left = right;
  }
}
template <typename T>
void ch_min(T &left, T right)
{
  if (left > right)
  {
    left = right;
  }
}
// ----- Mint -----
template <ll MOD = MOD>
class Mint
{
public:
  ll x;
  Mint() : x{0LL} {}
  Mint(ll x) : x{x % MOD} {}
  Mint operator-() const { return x ? MOD - x : 0; }
  Mint &operator+=(const Mint &a)
  {
    if ((x += a.x) >= MOD)
    {
      x -= MOD;
    }
    return *this;
  }
  Mint &operator-=(const Mint &a) { return *this += -a; }
  Mint &operator*=(const Mint &a)
  {
    (x *= a.x) %= MOD;
    return *this;
  }
  Mint &operator/=(const Mint &a)
  {
    Mint b{a};
    return *this *= b.power(MOD - 2);
  }
  Mint operator+(const Mint &a) const { return Mint(*this) += a; }
  Mint operator-(const Mint &a) const { return Mint(*this) -= a; }
  Mint operator*(const Mint &a) const { return Mint(*this) *= a; }
  Mint operator/(const Mint &a) const { return Mint(*this) /= a; }
  bool operator<(const Mint &a) const { return x < a.x; }
  bool operator<=(const Mint &a) const { return x <= a.x; }
  bool operator>(const Mint &a) const { return x > a.x; }
  bool operator>=(const Mint &a) const { return x >= a.x; }
  bool operator==(const Mint &a) const { return x == a.x; }
  bool operator!=(const Mint &a) const { return !(*this == a); }
  const Mint power(ll N)
  {
    if (N == 0)
    {
      return 1;
    }
    else if (N % 2 == 1)
    {
      return *this * power(N - 1);
    }
    else
    {
      Mint half = power(N / 2);
      return half * half;
    }
  }
};
template <ll MOD>
Mint<MOD> operator+(ll lhs, const Mint<MOD> &rhs)
{
  return rhs + lhs;
}
template <ll MOD>
Mint<MOD> operator-(ll lhs, const Mint<MOD> &rhs)
{
  return -rhs + lhs;
}
template <ll MOD>
Mint<MOD> operator*(ll lhs, const Mint<MOD> &rhs)
{
  return rhs * lhs;
}
template <ll MOD>
Mint<MOD> operator/(ll lhs, const Mint<MOD> &rhs)
{
  return Mint<MOD>{lhs} / rhs;
}
template <ll MOD>
istream &operator>>(istream &stream, Mint<MOD> &a)
{
  return stream >> a.x;
}
template <ll MOD>
ostream &operator<<(ostream &stream, const Mint<MOD> &a)
{
  return stream << a.x;
}
// ----- Combination -----
template <ll MOD = MOD, ll MAX_SIZE = MAX_SIZE>
class Combination
{
public:
  vector<Mint<MOD>> inv, fact, factinv;
  Combination() : inv(MAX_SIZE), fact(MAX_SIZE), factinv(MAX_SIZE)
  {
    inv[1] = 1;
    for (auto i = 2LL; i < MAX_SIZE; i++)
    {
      inv[i] = (-inv[MOD % i]) * (MOD / i);
    }
    fact[0] = factinv[0] = 1;
    for (auto i = 1LL; i < MAX_SIZE; i++)
    {
      fact[i] = Mint<MOD>(i) * fact[i - 1];
      factinv[i] = inv[i] * factinv[i - 1];
    }
  }
  Mint<MOD> operator()(int n, int k)
  {
    if (n >= 0 && k >= 0 && n - k >= 0)
    {
      return fact[n] * factinv[k] * factinv[n - k];
    }
    return 0;
  }
  Mint<MOD> catalan(int x, int y)
  {
    return (*this)(x + y, y) - (*this)(x + y, y - 1);
  }
};
// ----- for C++14 -----
using mint = Mint<MOD>;
using combination = Combination<MOD, MAX_SIZE>;
ll gcd(ll x, ll y) { return y ? gcd(y, x % y) : x; }
// ----- frequently used constexpr -----
// constexpr double epsilon{1e-10};
// constexpr ll infty{1000000000000000LL};
// constexpr int dx[4] = {1, 0, -1, 0};
// constexpr int dy[4] = {0, 1, 0, -1};
// ----- Yes() and No() -----
void Yes()
{
  cout << "Yes" << endl;
  exit(0);
}
void No()
{
  cout << "No" << endl;
  exit(0);
}

// ----- PrimeNums -----

class PrimeNums
{
  static constexpr ll MAX_SIZE{1000010LL};
  ll N;
  vector<bool> isprime;
  vector<int> prime_nums;

public:
  PrimeNums(ll N = MAX_SIZE) : N{N}, isprime(N, true), prime_nums{}
  {
    isprime[0] = isprime[1] = false;
    for (auto i = 2; i < N; i++)
    {
      if (isprime[i])
      {
        prime_nums.push_back(i);
        for (auto j = 2 * i; j < N; j += i)
        {
          isprime[j] = false;
        }
      }
    }
  }

  bool is_prime(long long x)
  { // 2 \leq x \leq MAX_SIZE^2
    if (x < N)
    {
      return isprime[x];
    }
    for (auto e : prime_nums)
    {
      if (x % e == 0)
        return false;
    }
    return true;
  }

  vector<int> const &primes() const
  {
    return prime_nums;
  }
};

// ----- main() -----
class Solve
{
  int H, W;
  vector<string> S;
  PrimeNums pn;

public:
  Solve(int H, int W, vector<string> const &S) : H{H}, W{W}, S(S), pn{} {}

  int calc()
  {
    int ans{0};
    for (auto i = 0; i < H; i++)
    {
      ans += calc(S[i]);
    }
    return ans;
  };

private:
  int calc(string const &T)
  {
    if (is_zero(T))
    {
      return 0;
    }
    auto V{make_vec(T)};
    if (is_one(V))
    {
      return 1;
    }
    if (is_two(V))
    {
      return 2;
    }
    return 3;
  }

  bool is_zero(string const &T)
  {
    for (auto x : T)
    {
      if (x == '.')
      {
        return false;
      }
    }
    return true;
  }

  vector<int> make_vec(string const &T)
  {
    int first{-1};
    vector<int> V;
    for (auto i = 0; i < W; i++)
    {
      if (T[i] == '.')
      {
        if (first == -1)
        {
          first = i;
        }
        V.push_back(i - first);
      }
    }
    return V;
  }

  bool is_one(vector<int> const &V)
  {
    if (V.size() < size_t{2})
    {
      return true;
    }
    assert(V[0] == 0);
    int g{V[1]};
    for (auto it = V.begin() + 1; it != V.end(); it++)
    {
      g = gcd(g, *it);
    }
    for (auto i = 0; i < 20; i++)
    {
      if (g == 1 << i)
      {
        return false;
      }
    }
    return true;
  }

  bool is_two(vector<int> const &V)
  {
    int X{static_cast<int>(V.size())};
    if (X <= 1)
    {
      assert(false);
      return false;
    }
    if (X == 2)
    {
      return true;
    }
    if (X == 3)
    {
      for (auto k = 0; k < 3; k++)
      {
        vector<int> W;
        for (auto i = 0; i < 3; i++)
        {
          if (i != k)
          {
            W.push_back(V[i]);
          }
        }
        if (is_one(W))
        {
          return true;
        }
      }
      return false;
    }
    for (auto it = pn.primes().begin() + 1; it != pn.primes().end(); it++)
    {
      int p{static_cast<int>(*it)};
      if (W / p < X / 2)
      {
        return false;
      }
      vector<int> M;
      M.push_back(0);
      for (auto i = 1; i < X; i++)
      {
        if (V[i] % p == 0)
        {
          continue;
        }
        M.push_back(V[i]);
        break;
      }
      for (auto m : M)
      {
        int first{-1};
        vector<int> W;
        for (auto x : V)
        {
          if ((x - m) % p == 0)
          {
            continue;
          }
          if (first == -1)
          {
            first = x;
          }
          W.push_back(x - first);
        }
        if (is_one(W))
        {
          return true;
        }
      }
    }
    assert(false);
    return false;
  }
};

int main()
{
  int H, W;
  cin >> H >> W;
  vector<string> S(H);
  for (auto i = 0; i < H; i++)
  {
    cin >> S[i];
  }
  Solve solve(H, W, S);
  cout << solve.calc() << endl;
}
<|endoftext|>


<commit_before>// Copyright 2008 Paul Hodge

#include "common_headers.h"

#include "tests/common.h"
#include "tokenizer.h"
#include "token_stream.h"
#include "errors.h"

namespace token = circa::tokenizer;

namespace circa {
namespace tokenizer_tests {

void test_identifiers()
{
    token::TokenList results;
    token::tokenize("word has_underscore has-hyphen,hasnumbers183", results);

    test_assert(results.size() == 7);

    test_assert(results[0].text == "word");
    test_assert(results[0].match == token::IDENTIFIER);
    test_assert(results[1].text == " ");
    test_assert(results[1].match == token::WHITESPACE);
    test_assert(results[2].text == "has_underscore");
    test_assert(results[2].match == token::IDENTIFIER);
    test_assert(results[3].text == " ");
    test_assert(results[3].match == token::WHITESPACE);
    test_assert(results[4].text == "has-hyphen");
    test_assert(results[4].match == token::IDENTIFIER);
    test_assert(results[5].text == ",");
    test_assert(results[5].match == token::COMMA);
    test_assert(results[6].text == "hasnumbers183");
    test_assert(results[6].match == token::IDENTIFIER);
}

void test_integers()
{
    token::TokenList results;
    token::tokenize("1 0 1234567890 -3", results);

    test_assert(results.size() == 7);
    test_assert(results[0].text == "1");
    test_assert(results[0].match == token::INTEGER);
    test_assert(results[1].text == " ");
    test_assert(results[1].match == token::WHITESPACE);
    test_assert(results[2].text == "0");
    test_assert(results[2].match == token::INTEGER);
    test_assert(results[3].text == " ");
    test_assert(results[3].match == token::WHITESPACE);
    test_assert(results[4].text == "1234567890");
    test_assert(results[4].match == token::INTEGER);
    test_assert(results[5].text == " ");
    test_assert(results[5].match == token::WHITESPACE);
    test_assert(results[6].text == "-3");
    test_assert(results[6].match == token::INTEGER);
}

void test_floats()
{
    token::TokenList results;
    token::tokenize("1.0 16. .483 .123. -0.1 -.54", results);

    test_assert(results[0].text == "1.0");
    test_assert(results[0].match == token::FLOAT);
    test_assert(results[2].text == "16.");
    test_assert(results[2].match == token::FLOAT);
    test_assert(results[4].text == ".483");
    test_assert(results[4].match == token::FLOAT);
    test_assert(results[6].text == ".123");
    test_assert(results[6].match == token::FLOAT);
    test_assert(results[7].text == ".");
    test_assert(results[7].match == token::DOT);
    test_assert(results[9].text == "-0.1");
    test_assert(results[9].match == token::FLOAT);
    test_assert(results[11].text == "-.54");
    test_assert(results[11].match == token::FLOAT);
    test_assert(results.size() == 12);
}

void test_symbols()
{
    token::TokenList results;
    token::tokenize(",()=?][", results);

    test_assert(results.size() == 7);
    test_assert(results[0].text == ",");
    test_assert(results[0].match == token::COMMA);
    test_assert(results[1].text == "(");
    test_assert(results[1].match == token::LPAREN);
    test_assert(results[2].text == ")");
    test_assert(results[2].match == token::RPAREN);
    test_assert(results[3].text == "=");
    test_assert(results[3].match == token::EQUALS);
    test_assert(results[4].text == "?");
    test_assert(results[4].match == token::QUESTION);
    test_assert(results[5].text == "]");
    test_assert(results[5].match == token::RBRACKET);
    test_assert(results[6].text == "[");
    test_assert(results[6].match == token::LBRACKET);
}

void test_string_literal()
{
    token::TokenList results;
    token::tokenize("\"string literal\"", results);

    test_assert(results.size() == 1);
    test_assert(results[0].text == "string literal");
    test_assert(results[0].match == token::STRING);
}

void test_token_stream()
{
    token_stream::TokenStream tstream("1 2.0");

    test_assert(tstream.nextIs(tokenizer::INTEGER));
    test_assert(tstream.nextIs(tokenizer::WHITESPACE, 1));
    test_assert(tstream.nextNonWhitespaceIs(tokenizer::FLOAT, 1));
}

void token_stream_to_string()
{
    token_stream::TokenStream tstream("hi + 0.123");

    test_assert(tstream.toString() ==
            "{index: 0, tokens: [IDENTIFIER \"hi\", WHITESPACE \" \", + \"+\", "
            "WHITESPACE \" \", FLOAT \"0.123\"]}");
}

} // namespace tokenizer_tests

void register_tokenizer_tests()
{
    REGISTER_TEST_CASE(tokenizer_tests::test_identifiers);
    REGISTER_TEST_CASE(tokenizer_tests::test_integers);
    REGISTER_TEST_CASE(tokenizer_tests::test_floats);
    REGISTER_TEST_CASE(tokenizer_tests::test_symbols);
    REGISTER_TEST_CASE(tokenizer_tests::test_string_literal);
    REGISTER_TEST_CASE(tokenizer_tests::test_token_stream);
    REGISTER_TEST_CASE(tokenizer_tests::token_stream_to_string);
}

} // namespace circa
<commit_msg>Add tokenizer_tests::hosted_tokenize<commit_after>// Copyright 2008 Paul Hodge

#include "common_headers.h"

#include "tests/common.h"
#include "branch.h"
#include "parser.h"
#include "builtins.h"
#include "term.h"
#include "runtime.h"
#include "tokenizer.h"
#include "token_stream.h"
#include "errors.h"

namespace token = circa::tokenizer;

namespace circa {
namespace tokenizer_tests {

void test_identifiers()
{
    token::TokenList results;
    token::tokenize("word has_underscore has-hyphen,hasnumbers183", results);

    test_assert(results.size() == 7);

    test_assert(results[0].text == "word");
    test_assert(results[0].match == token::IDENTIFIER);
    test_assert(results[1].text == " ");
    test_assert(results[1].match == token::WHITESPACE);
    test_assert(results[2].text == "has_underscore");
    test_assert(results[2].match == token::IDENTIFIER);
    test_assert(results[3].text == " ");
    test_assert(results[3].match == token::WHITESPACE);
    test_assert(results[4].text == "has-hyphen");
    test_assert(results[4].match == token::IDENTIFIER);
    test_assert(results[5].text == ",");
    test_assert(results[5].match == token::COMMA);
    test_assert(results[6].text == "hasnumbers183");
    test_assert(results[6].match == token::IDENTIFIER);
}

void test_integers()
{
    token::TokenList results;
    token::tokenize("1 0 1234567890 -3", results);

    test_assert(results.size() == 7);
    test_assert(results[0].text == "1");
    test_assert(results[0].match == token::INTEGER);
    test_assert(results[1].text == " ");
    test_assert(results[1].match == token::WHITESPACE);
    test_assert(results[2].text == "0");
    test_assert(results[2].match == token::INTEGER);
    test_assert(results[3].text == " ");
    test_assert(results[3].match == token::WHITESPACE);
    test_assert(results[4].text == "1234567890");
    test_assert(results[4].match == token::INTEGER);
    test_assert(results[5].text == " ");
    test_assert(results[5].match == token::WHITESPACE);
    test_assert(results[6].text == "-3");
    test_assert(results[6].match == token::INTEGER);
}

void test_floats()
{
    token::TokenList results;
    token::tokenize("1.0 16. .483 .123. -0.1 -.54", results);

    test_assert(results[0].text == "1.0");
    test_assert(results[0].match == token::FLOAT);
    test_assert(results[2].text == "16.");
    test_assert(results[2].match == token::FLOAT);
    test_assert(results[4].text == ".483");
    test_assert(results[4].match == token::FLOAT);
    test_assert(results[6].text == ".123");
    test_assert(results[6].match == token::FLOAT);
    test_assert(results[7].text == ".");
    test_assert(results[7].match == token::DOT);
    test_assert(results[9].text == "-0.1");
    test_assert(results[9].match == token::FLOAT);
    test_assert(results[11].text == "-.54");
    test_assert(results[11].match == token::FLOAT);
    test_assert(results.size() == 12);
}

void test_symbols()
{
    token::TokenList results;
    token::tokenize(",()=?][", results);

    test_assert(results.size() == 7);
    test_assert(results[0].text == ",");
    test_assert(results[0].match == token::COMMA);
    test_assert(results[1].text == "(");
    test_assert(results[1].match == token::LPAREN);
    test_assert(results[2].text == ")");
    test_assert(results[2].match == token::RPAREN);
    test_assert(results[3].text == "=");
    test_assert(results[3].match == token::EQUALS);
    test_assert(results[4].text == "?");
    test_assert(results[4].match == token::QUESTION);
    test_assert(results[5].text == "]");
    test_assert(results[5].match == token::RBRACKET);
    test_assert(results[6].text == "[");
    test_assert(results[6].match == token::LBRACKET);
}

void test_string_literal()
{
    token::TokenList results;
    token::tokenize("\"string literal\"", results);

    test_assert(results.size() == 1);
    test_assert(results[0].text == "string literal");
    test_assert(results[0].match == token::STRING);
}

void test_token_stream()
{
    token_stream::TokenStream tstream("1 2.0");

    test_assert(tstream.nextIs(tokenizer::INTEGER));
    test_assert(tstream.nextIs(tokenizer::WHITESPACE, 1));
    test_assert(tstream.nextNonWhitespaceIs(tokenizer::FLOAT, 1));
}

void token_stream_to_string()
{
    token_stream::TokenStream tstream("hi + 0.123");

    test_assert(tstream.toString() ==
            "{index: 0, tokens: [IDENTIFIER \"hi\", WHITESPACE \" \", + \"+\", "
            "WHITESPACE \" \", FLOAT \"0.123\"]}");
}

void hosted_tokenize()
{
    Branch branch;
    Term* result = eval_statement(branch, "\"hi + 0.123\" -> tokenize -> to-string");

    test_assert(as_string(result) ==
            "{index: 0, tokens: [IDENTIFIER \"hi\", WHITESPACE \" \", + \"+\", "
            "WHITESPACE \" \", FLOAT \"0.123\"]}");
}

} // namespace tokenizer_tests

void register_tokenizer_tests()
{
    REGISTER_TEST_CASE(tokenizer_tests::test_identifiers);
    REGISTER_TEST_CASE(tokenizer_tests::test_integers);
    REGISTER_TEST_CASE(tokenizer_tests::test_floats);
    REGISTER_TEST_CASE(tokenizer_tests::test_symbols);
    REGISTER_TEST_CASE(tokenizer_tests::test_string_literal);
    REGISTER_TEST_CASE(tokenizer_tests::test_token_stream);
    REGISTER_TEST_CASE(tokenizer_tests::token_stream_to_string);
    REGISTER_TEST_CASE(tokenizer_tests::hosted_tokenize);
}

} // namespace circa
<|endoftext|>