<commit_before>#include <stdexcept>
#include <unordered_map>

#include "windowsx.h"

#include "windowswindow.hh"
#include "windowsopenglcontext.hh"
#include "system/mousebutton.hh"
#include "system/keycode.hh"

static char appName[] = "Test Application";

using System::KeyCode;

class KeyMap : public std::unordered_map<WPARAM, System::KeyCode>
{
public:
    KeyMap() : std::unordered_map<WPARAM, System::KeyCode>() {
        (*this)[VK_PRIOR]   = KeyCode::KeyPageUp;
        (*this)[VK_NEXT]    = KeyCode::KeyPageDown;
        (*this)[VK_END]     = KeyCode::KeyEnd;
        (*this)[VK_HOME]    = KeyCode::KeyHome;
        (*this)[VK_INSERT]  = KeyCode::KeyInsert;
        (*this)[VK_DELETE]  = KeyCode::KeyDelete;

        (*this)[VK_RIGHT]   = KeyCode::KeyRightArrow;
        (*this)[VK_DOWN]    = KeyCode::KeyDownArrow;
        (*this)[VK_LEFT]    = KeyCode::KeyLeftArrow;
        (*this)[VK_UP]      = KeyCode::KeyUpArrow;

        (*this)[VK_ESCAPE]  = KeyCode::KeyEscape;
        (*this)[VK_TAB]     = KeyCode::KeyTab;
        (*this)[VK_SHIFT]   = KeyCode::KeyShift;
        (*this)[VK_MENU]    = KeyCode::KeyAlt;
        (*this)[VK_CONTROL] = KeyCode::KeyControl;
        (*this)[VK_CAPITAL] = KeyCode::KeyCapsLock;

        (*this)[VK_RCONTROL] = KeyCode::KeyRightControl;
        (*this)[VK_LCONTROL] = KeyCode::KeyLeftControl;
        (*this)[VK_RSHIFT]   = KeyCode::KeyRightShift;
        (*this)[VK_LSHIFT]   = KeyCode::KeyLeftShift;

        (*this)[VK_BACK]    = KeyCode::KeyBackspace;
        (*this)[VK_RETURN]  = KeyCode::KeyEnter;
        (*this)[VK_SPACE]   = KeyCode::KeySpace;

        (*this)[0x30]       = KeyCode::Key0;
        (*this)[0x31]       = KeyCode::Key1;
        (*this)[0x32]       = KeyCode::Key2;
        (*this)[0x33]       = KeyCode::Key3;
        (*this)[0x34]       = KeyCode::Key4;
        (*this)[0x35]       = KeyCode::Key5;
        (*this)[0x36]       = KeyCode::Key6;
        (*this)[0x37]       = KeyCode::Key7;
        (*this)[0x38]       = KeyCode::Key8;
        (*this)[0x39]       = KeyCode::Key9;

        (*this)[VK_NUMPAD0] = KeyCode::KeyNumpad0;
        (*this)[VK_NUMPAD1] = KeyCode::KeyNumpad1;
        (*this)[VK_NUMPAD2] = KeyCode::KeyNumpad2;
        (*this)[VK_NUMPAD3] = KeyCode::KeyNumpad3;
        (*this)[VK_NUMPAD4] = KeyCode::KeyNumpad4;
        (*this)[VK_NUMPAD5] = KeyCode::KeyNumpad5;
        (*this)[VK_NUMPAD6] = KeyCode::KeyNumpad6;
        (*this)[VK_NUMPAD7] = KeyCode::KeyNumpad7;
        (*this)[VK_NUMPAD8] = KeyCode::KeyNumpad8;
        (*this)[VK_NUMPAD9] = KeyCode::KeyNumpad9;

        (*this)[VK_MULTIPLY] = KeyCode::KeyMultiply;
        (*this)[VK_ADD]      = KeyCode::KeyPlus;
        (*this)[VK_SUBTRACT] = KeyCode::KeyMinus;
        (*this)[VK_DIVIDE]   = KeyCode::KeyDivide;
        (*this)[VK_DECIMAL]  = KeyCode::KeyDecimal;

        (*this)[0x41]       = KeyCode::KeyA;
        (*this)[0x42]       = KeyCode::KeyB;
        (*this)[0x43]       = KeyCode::KeyC;
        (*this)[0x44]       = KeyCode::KeyD;
        (*this)[0x45]       = KeyCode::KeyE;
        (*this)[0x46]       = KeyCode::KeyF;
        (*this)[0x47]       = KeyCode::KeyG;
        (*this)[0x48]       = KeyCode::KeyH;
        (*this)[0x49]       = KeyCode::KeyI;
        (*this)[0x4A]       = KeyCode::KeyJ;
        (*this)[0x4B]       = KeyCode::KeyK;
        (*this)[0x4C]       = KeyCode::KeyL;
        (*this)[0x4D]       = KeyCode::KeyM;
        (*this)[0x4E]       = KeyCode::KeyN;
        (*this)[0x4F]       = KeyCode::KeyO;
        (*this)[0x50]       = KeyCode::KeyP;
        (*this)[0x51]       = KeyCode::KeyQ;
        (*this)[0x52]       = KeyCode::KeyR;
        (*this)[0x53]       = KeyCode::KeyS;
        (*this)[0x54]       = KeyCode::KeyT;
        (*this)[0x55]       = KeyCode::KeyU;
        (*this)[0x56]       = KeyCode::KeyV;
        (*this)[0x57]       = KeyCode::KeyW;
        (*this)[0x59]       = KeyCode::KeyY;
        (*this)[0x5A]       = KeyCode::KeyZ;
    }
};

static KeyMap keyMap;
static std::unordered_map<HWND, WindowsWindow*> windowMap;

WindowsWindow::WindowsWindow(const char *windowName, Framework::ISystemWindowController *controller, HINSTANCE processInstance, int commandShow)
    : m_controller(controller), m_openGLContext(NULL)
{
    m_windowHandle = WindowsWindow::makeWindow(windowName, processInstance, commandShow);
    windowMap[m_windowHandle] = this;

    ShowWindow(m_windowHandle, commandShow);
    UpdateWindow(m_windowHandle);

    unsigned int windowWidth, windowHeight;
    GetWindowSize(&windowWidth, &windowHeight);
    m_controller->OnWindowResize(windowWidth, windowHeight);
}

HWND WindowsWindow::makeWindow(const char *windowName, HINSTANCE processInstance, int commandShow)
{
    WNDCLASSEX windowClass;

    windowClass.cbSize        = sizeof(WNDCLASSEX);
    windowClass.style         = CS_VREDRAW | CS_HREDRAW;
    windowClass.lpfnWndProc   = WndProc;
    windowClass.cbClsExtra    = 0;
    windowClass.cbWndExtra    = 0;
    windowClass.hInstance     = processInstance;
    windowClass.hIcon         = LoadIcon(NULL, IDI_APPLICATION);
    windowClass.hIconSm       = LoadIcon(NULL, IDI_APPLICATION);
    windowClass.hCursor       = LoadCursor(NULL, IDC_ARROW);
    windowClass.hbrBackground = (HBRUSH) GetStockObject(BLACK_BRUSH);
    windowClass.lpszClassName = appName;
    windowClass.lpszMenuName  = NULL;

    RegisterClassEx(&windowClass);

    return CreateWindow(appName, windowName, WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, processInstance, NULL);
}

WindowsWindow::~WindowsWindow()
{
    if (m_openGLContext != NULL)
        delete m_openGLContext;

    windowMap[m_windowHandle] = NULL;
}

int WindowsWindow::DoMessageLoop()
{
    MSG message;

    Ready();

    while (GetMessage(&message, NULL, 0, 0))
    {
        TranslateMessage(&message);
        DispatchMessage(&message);
    }

    return message.wParam;
}

System::OpenGLContext *WindowsWindow::getOrCreateOpenGLContext()
{
    if (m_openGLContext == NULL)
        m_openGLContext = new WindowsOpenGLContext(m_windowHandle);

    return m_openGLContext;
}

void WindowsWindow::GetWindowSize(unsigned int *width, unsigned int *height)
{
    RECT rect;

    GetClientRect(m_windowHandle, &rect);

    *width = rect.right - rect.left;
    *height = rect.bottom - rect.top;
}

bool WindowsWindow::SetMousePosition(unsigned int posX, unsigned int posY)
{
    POINT point;

    point.x = posX;
    point.y = posY;

    bool success = ClientToScreen(m_windowHandle, &point) ? SetCursorPos(point.x, point.y) : false;
    if (success)
        m_controller->OnMouseMove(point.x, point.y);

    return success;
}

void WindowsWindow::Destroy()
{
    SendNotifyMessage(m_windowHandle, WM_DESTROY, 0, 0);
}

void WindowsWindow::Close()
{
    SendNotifyMessage(m_windowHandle, WM_CLOSE, 0, 0);
}

void WindowsWindow::Ready()
{
    m_controller->OnWindowReady();
}

void WindowsWindow::onClose()
{
    m_controller->OnWindowClose();
}

void WindowsWindow::KeyDown(WPARAM key)
{
    m_controller->OnKeyDown(keyMap[key]);
}

void WindowsWindow::WindowResize(WPARAM wParam, LPARAM lParam)
{
    m_controller->OnWindowResize(LOWORD(lParam), HIWORD(lParam));
}

void WindowsWindow::KeyUp(WPARAM key)
{
    m_controller->OnKeyUp(keyMap[key]);
}

void WindowsWindow::MouseMove(WPARAM wParam, LPARAM lParam)
{
    m_controller->OnMouseMove(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam));
}

void WindowsWindow::LeftMouseButtonDown(WPARAM wParam, LPARAM lParam)
{
    m_controller->OnMouseButtonDown(System::MouseButton::ButtonOne);
}

void WindowsWindow::RightMouseButtonDown(WPARAM wParam, LPARAM lParam)
{
    m_controller->OnMouseButtonDown(System::MouseButton::ButtonTwo);
}

void WindowsWindow::LeftMouseButtonUp(WPARAM wParam, LPARAM lParam)
{
    m_controller->OnMouseButtonUp(System::MouseButton::ButtonOne);
}

void WindowsWindow::RightMouseButtonUp(WPARAM wParam, LPARAM lParam)
{
    m_controller->OnMouseButtonUp(System::MouseButton::ButtonTwo);
}

void WindowsWindow::MouseScrollWheel(WPARAM wParam, LPARAM lParam)
{
    m_controller->OnMouseScroll(GET_WHEEL_DELTA_WPARAM(wParam) / WHEEL_DELTA);
}

LRESULT CALLBACK WindowsWindow::WndProc(HWND windowHandle, UINT message, WPARAM wparam, LPARAM lparam)
{
    WindowsWindow *window;

    try
    {
        window = windowMap.at(windowHandle);
    }
    catch (std::out_of_range e)
    {
        return DefWindowProc(windowHandle, message, wparam, lparam);
    }

    switch(message)
    {
    case WM_KEYDOWN:
        window->KeyDown(wparam);
        return 0;

    case WM_KEYUP:
        window->KeyUp(wparam);
        return 0;

    case WM_MOUSEMOVE:
        window->MouseMove(wparam, lparam);
        return 0;

    case WM_LBUTTONDOWN:
        window->LeftMouseButtonDown(wparam, lparam);
        return 0;

    case WM_LBUTTONUP:
        window->LeftMouseButtonUp(wparam, lparam);
        return 0;

    case WM_RBUTTONDOWN:
        window->RightMouseButtonDown(wparam, lparam);
        return 0;

    case WM_RBUTTONUP:
        window->RightMouseButtonUp(wparam, lparam);
        return 0;

    case WM_MOUSEWHEEL:
        window->MouseScrollWheel(wparam, lparam);
        return 0;

    case WM_SIZE:
        window->WindowResize(wparam, lparam);
        return 0;

    case WM_CLOSE:
        window->onClose();
        return 0;

    case WM_DESTROY:
        PostQuitMessage(0);
        windowMap[windowHandle] = NULL;
        return 0;
    }

    return DefWindowProc(windowHandle, message, wparam, lparam);
}
<commit_msg>Add some beginnings for borderless fullscreen<commit_after>#include <stdexcept>
#include <unordered_map>

#include "windowsx.h"

#include "windowswindow.hh"
#include "windowsopenglcontext.hh"
#include "system/mousebutton.hh"
#include "system/keycode.hh"

static char appName[] = "Test Application";

using System::KeyCode;

class KeyMap : public std::unordered_map<WPARAM, System::KeyCode>
{
public:
    KeyMap() : std::unordered_map<WPARAM, System::KeyCode>() {
        (*this)[VK_PRIOR]   = KeyCode::KeyPageUp;
        (*this)[VK_NEXT]    = KeyCode::KeyPageDown;
        (*this)[VK_END]     = KeyCode::KeyEnd;
        (*this)[VK_HOME]    = KeyCode::KeyHome;
        (*this)[VK_INSERT]  = KeyCode::KeyInsert;
        (*this)[VK_DELETE]  = KeyCode::KeyDelete;

        (*this)[VK_RIGHT]   = KeyCode::KeyRightArrow;
        (*this)[VK_DOWN]    = KeyCode::KeyDownArrow;
        (*this)[VK_LEFT]    = KeyCode::KeyLeftArrow;
        (*this)[VK_UP]      = KeyCode::KeyUpArrow;

        (*this)[VK_ESCAPE]  = KeyCode::KeyEscape;
        (*this)[VK_TAB]     = KeyCode::KeyTab;
        (*this)[VK_SHIFT]   = KeyCode::KeyShift;
        (*this)[VK_MENU]    = KeyCode::KeyAlt;
        (*this)[VK_CONTROL] = KeyCode::KeyControl;
        (*this)[VK_CAPITAL] = KeyCode::KeyCapsLock;

        (*this)[VK_RCONTROL] = KeyCode::KeyRightControl;
        (*this)[VK_LCONTROL] = KeyCode::KeyLeftControl;
        (*this)[VK_RSHIFT]   = KeyCode::KeyRightShift;
        (*this)[VK_LSHIFT]   = KeyCode::KeyLeftShift;

        (*this)[VK_BACK]    = KeyCode::KeyBackspace;
        (*this)[VK_RETURN]  = KeyCode::KeyEnter;
        (*this)[VK_SPACE]   = KeyCode::KeySpace;

        (*this)[0x30]       = KeyCode::Key0;
        (*this)[0x31]       = KeyCode::Key1;
        (*this)[0x32]       = KeyCode::Key2;
        (*this)[0x33]       = KeyCode::Key3;
        (*this)[0x34]       = KeyCode::Key4;
        (*this)[0x35]       = KeyCode::Key5;
        (*this)[0x36]       = KeyCode::Key6;
        (*this)[0x37]       = KeyCode::Key7;
        (*this)[0x38]       = KeyCode::Key8;
        (*this)[0x39]       = KeyCode::Key9;

        (*this)[VK_NUMPAD0] = KeyCode::KeyNumpad0;
        (*this)[VK_NUMPAD1] = KeyCode::KeyNumpad1;
        (*this)[VK_NUMPAD2] = KeyCode::KeyNumpad2;
        (*this)[VK_NUMPAD3] = KeyCode::KeyNumpad3;
        (*this)[VK_NUMPAD4] = KeyCode::KeyNumpad4;
        (*this)[VK_NUMPAD5] = KeyCode::KeyNumpad5;
        (*this)[VK_NUMPAD6] = KeyCode::KeyNumpad6;
        (*this)[VK_NUMPAD7] = KeyCode::KeyNumpad7;
        (*this)[VK_NUMPAD8] = KeyCode::KeyNumpad8;
        (*this)[VK_NUMPAD9] = KeyCode::KeyNumpad9;

        (*this)[VK_MULTIPLY] = KeyCode::KeyMultiply;
        (*this)[VK_ADD]      = KeyCode::KeyPlus;
        (*this)[VK_SUBTRACT] = KeyCode::KeyMinus;
        (*this)[VK_DIVIDE]   = KeyCode::KeyDivide;
        (*this)[VK_DECIMAL]  = KeyCode::KeyDecimal;

        (*this)[0x41]       = KeyCode::KeyA;
        (*this)[0x42]       = KeyCode::KeyB;
        (*this)[0x43]       = KeyCode::KeyC;
        (*this)[0x44]       = KeyCode::KeyD;
        (*this)[0x45]       = KeyCode::KeyE;
        (*this)[0x46]       = KeyCode::KeyF;
        (*this)[0x47]       = KeyCode::KeyG;
        (*this)[0x48]       = KeyCode::KeyH;
        (*this)[0x49]       = KeyCode::KeyI;
        (*this)[0x4A]       = KeyCode::KeyJ;
        (*this)[0x4B]       = KeyCode::KeyK;
        (*this)[0x4C]       = KeyCode::KeyL;
        (*this)[0x4D]       = KeyCode::KeyM;
        (*this)[0x4E]       = KeyCode::KeyN;
        (*this)[0x4F]       = KeyCode::KeyO;
        (*this)[0x50]       = KeyCode::KeyP;
        (*this)[0x51]       = KeyCode::KeyQ;
        (*this)[0x52]       = KeyCode::KeyR;
        (*this)[0x53]       = KeyCode::KeyS;
        (*this)[0x54]       = KeyCode::KeyT;
        (*this)[0x55]       = KeyCode::KeyU;
        (*this)[0x56]       = KeyCode::KeyV;
        (*this)[0x57]       = KeyCode::KeyW;
        (*this)[0x59]       = KeyCode::KeyY;
        (*this)[0x5A]       = KeyCode::KeyZ;
    }
};

static KeyMap keyMap;
static std::unordered_map<HWND, WindowsWindow*> windowMap;

WindowsWindow::WindowsWindow(const char *windowName, Framework::ISystemWindowController *controller, HINSTANCE processInstance, int commandShow)
    : m_controller(controller), m_openGLContext(NULL)
{
    m_windowHandle = WindowsWindow::makeWindow(windowName, processInstance, commandShow);
    windowMap[m_windowHandle] = this;

    ShowWindow(m_windowHandle, commandShow);
    UpdateWindow(m_windowHandle);

    unsigned int windowWidth, windowHeight;
    GetWindowSize(&windowWidth, &windowHeight);
    m_controller->OnWindowResize(windowWidth, windowHeight);
}

HWND WindowsWindow::makeWindow(const char *windowName, HINSTANCE processInstance, int commandShow)
{
    WNDCLASSEX windowClass;

    windowClass.cbSize        = sizeof(WNDCLASSEX);
    windowClass.style         = CS_VREDRAW | CS_HREDRAW;
    windowClass.lpfnWndProc   = WndProc;
    windowClass.cbClsExtra    = 0;
    windowClass.cbWndExtra    = 0;
    windowClass.hInstance     = processInstance;
    windowClass.hIcon         = LoadIcon(NULL, IDI_APPLICATION);
    windowClass.hIconSm       = LoadIcon(NULL, IDI_APPLICATION);
    windowClass.hCursor       = LoadCursor(NULL, IDC_ARROW);
    windowClass.hbrBackground = (HBRUSH) GetStockObject(BLACK_BRUSH);
    windowClass.lpszClassName = appName;
    windowClass.lpszMenuName  = NULL;

    RegisterClassEx(&windowClass);

    POINT point = {0, 0};
    HMONITOR hmon = MonitorFromPoint(point, MONITOR_DEFAULTTONEAREST);
    MONITORINFO mi = { sizeof(mi) };
    if (!GetMonitorInfo(hmon, &mi))
        return NULL;

    //return CreateWindow(appName, windowName, WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, processInstance, NULL);
    return CreateWindow(appName, windowName, WS_POPUP,
                        mi.rcMonitor.left, mi.rcMonitor.top,
                        mi.rcMonitor.right - mi.rcMonitor.left, mi.rcMonitor.bottom - mi.rcMonitor.top,
                        NULL, NULL, processInstance, NULL);
}

WindowsWindow::~WindowsWindow()
{
    if (m_openGLContext != NULL)
        delete m_openGLContext;

    windowMap[m_windowHandle] = NULL;
}

int WindowsWindow::DoMessageLoop()
{
    MSG message;

    Ready();

    while (GetMessage(&message, NULL, 0, 0))
    {
        TranslateMessage(&message);
        DispatchMessage(&message);
    }

    return message.wParam;
}

System::OpenGLContext *WindowsWindow::getOrCreateOpenGLContext()
{
    if (m_openGLContext == NULL)
        m_openGLContext = new WindowsOpenGLContext(m_windowHandle);

    return m_openGLContext;
}

void WindowsWindow::GetWindowSize(unsigned int *width, unsigned int *height)
{
    RECT rect;

    GetClientRect(m_windowHandle, &rect);

    *width = rect.right - rect.left;
    *height = rect.bottom - rect.top;
}

bool WindowsWindow::SetMousePosition(unsigned int posX, unsigned int posY)
{
    POINT point;

    point.x = posX;
    point.y = posY;

    bool success = ClientToScreen(m_windowHandle, &point) ? SetCursorPos(point.x, point.y) : false;
    if (success)
        m_controller->OnMouseMove(point.x, point.y);

    return success;
}

void WindowsWindow::Destroy()
{
    SendNotifyMessage(m_windowHandle, WM_DESTROY, 0, 0);
}

void WindowsWindow::Close()
{
    SendNotifyMessage(m_windowHandle, WM_CLOSE, 0, 0);
}

void WindowsWindow::Ready()
{
    m_controller->OnWindowReady();
}

void WindowsWindow::onClose()
{
    m_controller->OnWindowClose();
}

void WindowsWindow::KeyDown(WPARAM key)
{
    m_controller->OnKeyDown(keyMap[key]);
}

void WindowsWindow::WindowResize(WPARAM wParam, LPARAM lParam)
{
    m_controller->OnWindowResize(LOWORD(lParam), HIWORD(lParam));
}

void WindowsWindow::KeyUp(WPARAM key)
{
    m_controller->OnKeyUp(keyMap[key]);
}

void WindowsWindow::MouseMove(WPARAM wParam, LPARAM lParam)
{
    m_controller->OnMouseMove(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam));
}

void WindowsWindow::LeftMouseButtonDown(WPARAM wParam, LPARAM lParam)
{
    m_controller->OnMouseButtonDown(System::MouseButton::ButtonOne);
}

void WindowsWindow::RightMouseButtonDown(WPARAM wParam, LPARAM lParam)
{
    m_controller->OnMouseButtonDown(System::MouseButton::ButtonTwo);
}

void WindowsWindow::LeftMouseButtonUp(WPARAM wParam, LPARAM lParam)
{
    m_controller->OnMouseButtonUp(System::MouseButton::ButtonOne);
}

void WindowsWindow::RightMouseButtonUp(WPARAM wParam, LPARAM lParam)
{
    m_controller->OnMouseButtonUp(System::MouseButton::ButtonTwo);
}

void WindowsWindow::MouseScrollWheel(WPARAM wParam, LPARAM lParam)
{
    m_controller->OnMouseScroll(GET_WHEEL_DELTA_WPARAM(wParam) / WHEEL_DELTA);
}

LRESULT CALLBACK WindowsWindow::WndProc(HWND windowHandle, UINT message, WPARAM wparam, LPARAM lparam)
{
    WindowsWindow *window;

    try
    {
        window = windowMap.at(windowHandle);
    }
    catch (std::out_of_range e)
    {
        return DefWindowProc(windowHandle, message, wparam, lparam);
    }

    switch(message)
    {
    case WM_KEYDOWN:
        window->KeyDown(wparam);
        return 0;

    case WM_KEYUP:
        window->KeyUp(wparam);
        return 0;

    case WM_MOUSEMOVE:
        window->MouseMove(wparam, lparam);
        return 0;

    case WM_LBUTTONDOWN:
        window->LeftMouseButtonDown(wparam, lparam);
        return 0;

    case WM_LBUTTONUP:
        window->LeftMouseButtonUp(wparam, lparam);
        return 0;

    case WM_RBUTTONDOWN:
        window->RightMouseButtonDown(wparam, lparam);
        return 0;

    case WM_RBUTTONUP:
        window->RightMouseButtonUp(wparam, lparam);
        return 0;

    case WM_MOUSEWHEEL:
        window->MouseScrollWheel(wparam, lparam);
        return 0;

    case WM_SIZE:
        window->WindowResize(wparam, lparam);
        return 0;

    case WM_CLOSE:
        window->onClose();
        return 0;

    case WM_DESTROY:
        PostQuitMessage(0);
        windowMap[windowHandle] = NULL;
        return 0;
    }

    return DefWindowProc(windowHandle, message, wparam, lparam);
}
<|endoftext|>


<commit_before>#if !defined(h_3e645482_ae6a_43e5_8f81_abbc4200212d)
#define h_3e645482_ae6a_43e5_8f81_abbc4200212d

#include <map>
#include <string>
#include <sstream>
#include <stdexcept>
#include "Portability.hh"

namespace log4cpp
{
   class FactoryParams;
   namespace details
   {
      class base_validator_data
      {
         public:
            base_validator_data(const char* tag, const FactoryParams* params) : tag_(tag), params_(params){}

         protected:
            const char* tag_;
            const FactoryParams* params_;

            template<typename T>
            void assign(const std::string& param_value, T& value) const
            {
               assign_impl(param_value, value);
            }

            template<typename T>
            void assign_impl(const std::string& param_value, T& value) const
            {
               std::stringstream s;
               s << param_value;
               s >> value;
            }

            void assign_impl(const std::string& param_value, std::string& value) const
            {
               value = param_value;
            }

            void throw_error(const char* param_name) const
            {
               std::stringstream s;
               s << "Property '" << param_name << "' required to configure " << tag_;
               throw std::runtime_error(s.str());
            }
      };

      class optional_params_validator;
      class required_params_validator : public base_validator_data
      {
         public:
            required_params_validator(const char* tag, const FactoryParams* params) : base_validator_data(tag, params) {}

            template<typename T>
            optional_params_validator optional(const char* param, T& value) const;

            template<typename T>
            const required_params_validator& operator()(const char* param, T& value) const;
      };

      class optional_params_validator : public base_validator_data
      {
         public:
            optional_params_validator(const char* tag, const FactoryParams* params) : base_validator_data(tag, params) {}

            template<typename T>
            required_params_validator required(const char* param, T& value) const { required_params_validator v(tag_, params_); v(param, value); return v; }

            template<typename T>
            const optional_params_validator& operator()(const char* param, T& value) const;
      };

      template<typename T>
      optional_params_validator required_params_validator::optional(const char* param, T& value) const { optional_params_validator v(tag_, params_); v(param, value); return v; }

      class parameter_validator : public base_validator_data
      {
         public:
            parameter_validator(const char* tag, const FactoryParams* params) : base_validator_data(tag, params) {}

            template<typename T>
            required_params_validator required(const char* param, T& value) const { required_params_validator v(tag_, params_); v(param, value); return v; }

            template<typename T>
            optional_params_validator optional(const char* param, T& value) const { optional_params_validator v(tag_, params_); v(param, value); return v; }
      };
   }

   class LOG4CPP_EXPORT FactoryParams
   {
         typedef std::map<std::string, std::string> storage_t;

      public:
         typedef storage_t::const_iterator const_iterator;

         const std::string& operator[](const std::string& v) const;
         std::string& operator[](const std::string& v) { return storage_[v]; }
         details::parameter_validator get_for(const char* tag) const { return details::parameter_validator(tag, this); }
         const_iterator find(const std::string& t) const;
         const_iterator begin() const { return storage_.begin(); }
         const_iterator end() const { return storage_.end(); }

      private:
         typedef std::map<std::string, std::string> storage_t;

         storage_t storage_;
   };

   namespace details
   {
      template<typename T>
      const required_params_validator& required_params_validator::operator()(const char* param, T& value) const
      {
         FactoryParams::const_iterator i = params_->find(param);
         if (i != params_->end())
            assign(i->second, value);
         else
            throw_error(param);

         return *this;
      }

      template<typename T>
      const optional_params_validator& optional_params_validator::operator()(const char* param, T& value) const
      {
         FactoryParams::const_iterator i = params_->find(param);
         if (i != params_->end())
            assign(i->second, value);

         return *this;
      }
   }
}

#endif // h_3e645482_ae6a_43e5_8f81_abbc4200212d
<commit_msg>[bug] fixed build problem under linux<commit_after>#if !defined(h_3e645482_ae6a_43e5_8f81_abbc4200212d)
#define h_3e645482_ae6a_43e5_8f81_abbc4200212d

#include <map>
#include <string>
#include <sstream>
#include <stdexcept>
#include "Portability.hh"

namespace log4cpp
{
   class FactoryParams;
   namespace details
   {
      class base_validator_data
      {
         public:
            base_validator_data(const char* tag, const FactoryParams* params) : tag_(tag), params_(params){}

         protected:
            const char* tag_;
            const FactoryParams* params_;

            template<typename T>
            void assign(const std::string& param_value, T& value) const
            {
               assign_impl(param_value, value);
            }

            template<typename T>
            void assign_impl(const std::string& param_value, T& value) const
            {
               std::stringstream s;
               s << param_value;
               s >> value;
            }

            void assign_impl(const std::string& param_value, std::string& value) const
            {
               value = param_value;
            }

            void throw_error(const char* param_name) const
            {
               std::stringstream s;
               s << "Property '" << param_name << "' required to configure " << tag_;
               throw std::runtime_error(s.str());
            }
      };

      class optional_params_validator;
      class required_params_validator : public base_validator_data
      {
         public:
            required_params_validator(const char* tag, const FactoryParams* params) : base_validator_data(tag, params) {}

            template<typename T>
            optional_params_validator optional(const char* param, T& value) const;

            template<typename T>
            const required_params_validator& operator()(const char* param, T& value) const;
      };

      class optional_params_validator : public base_validator_data
      {
         public:
            optional_params_validator(const char* tag, const FactoryParams* params) : base_validator_data(tag, params) {}

            template<typename T>
            required_params_validator required(const char* param, T& value) const { required_params_validator v(tag_, params_); v(param, value); return v; }

            template<typename T>
            const optional_params_validator& operator()(const char* param, T& value) const;
      };

      template<typename T>
      optional_params_validator required_params_validator::optional(const char* param, T& value) const { optional_params_validator v(tag_, params_); v(param, value); return v; }

      class parameter_validator : public base_validator_data
      {
         public:
            parameter_validator(const char* tag, const FactoryParams* params) : base_validator_data(tag, params) {}

            template<typename T>
            required_params_validator required(const char* param, T& value) const { required_params_validator v(tag_, params_); v(param, value); return v; }

            template<typename T>
            optional_params_validator optional(const char* param, T& value) const { optional_params_validator v(tag_, params_); v(param, value); return v; }
      };
   }

   class LOG4CPP_EXPORT FactoryParams
   {
         typedef std::map<std::string, std::string> storage_t;

		 		 storage_t storage_;

      public:
         typedef storage_t::const_iterator const_iterator;

         const std::string& operator[](const std::string& v) const;
         std::string& operator[](const std::string& v) { return storage_[v]; }
         details::parameter_validator get_for(const char* tag) const { return details::parameter_validator(tag, this); }
         const_iterator find(const std::string& t) const;
         const_iterator begin() const { return storage_.begin(); }
         const_iterator end() const { return storage_.end(); }

      private:
         /*typedef std::map<std::string, std::string> storage_t;

         storage_t storage_; */
   };

   namespace details
   {
      template<typename T>
      const required_params_validator& required_params_validator::operator()(const char* param, T& value) const
      {
         FactoryParams::const_iterator i = params_->find(param);
         if (i != params_->end())
            assign(i->second, value);
         else
            throw_error(param);

         return *this;
      }

      template<typename T>
      const optional_params_validator& optional_params_validator::operator()(const char* param, T& value) const
      {
         FactoryParams::const_iterator i = params_->find(param);
         if (i != params_->end())
            assign(i->second, value);

         return *this;
      }
   }
}

#endif // h_3e645482_ae6a_43e5_8f81_abbc4200212d
<|endoftext|>


<commit_before>#include <memory>
#include <string>
#include <uv.h>
#include <vector>

#include "../log.h"
#include "../message.h"
#include "../queue.h"
#include "../result.h"
#include "worker_platform.h"
#include "worker_thread.h"

using std::string;
using std::unique_ptr;

WorkerThread::WorkerThread(uv_async_t *main_callback) :
  Thread("worker thread", main_callback),
  platform{WorkerPlatform::for_worker(this)}
{
  //
}

// Definition must be here to see the full definition of WorkerPlatform.
WorkerThread::~WorkerThread() = default;

Result<> WorkerThread::wake()
{
  if (!is_healthy()) return health_err_result();

  return platform->wake();
}

Result<> WorkerThread::body()
{
  return platform->listen();
}

Result<Thread::CommandOutcome> WorkerThread::handle_add_command(const CommandPayload *payload)
{
  Result<bool> r = platform->handle_add_command(
    payload->get_id(), payload->get_channel_id(), payload->get_root(), payload->get_recursive());
  if (r.is_error()) return r.propagate<CommandOutcome>();

  return ok_result(r.get_value() ? ACK : NOTHING);
}

Result<Thread::CommandOutcome> WorkerThread::handle_remove_command(const CommandPayload *payload)
{
  Result<bool> r = platform->handle_remove_command(payload->get_id(), payload->get_channel_id());
  if (r.is_error()) return r.propagate<CommandOutcome>();

  return ok_result(r.get_value() ? ACK : NOTHING);
}

void WorkerThread::collect_status(Status &status)
{
  status.worker_thread_state = state_name();
  status.worker_thread_ok = get_error();
  status.worker_in_size = get_in_queue_size();
  status.worker_in_ok = get_in_queue_error();
  status.worker_out_size = get_out_queue_size();
  status.worker_out_ok = get_out_queue_error();
}
<commit_msg>Tidy up Result<> returns<commit_after>#include <memory>
#include <string>
#include <uv.h>
#include <vector>

#include "../log.h"
#include "../message.h"
#include "../queue.h"
#include "../result.h"
#include "worker_platform.h"
#include "worker_thread.h"

using std::string;
using std::unique_ptr;

WorkerThread::WorkerThread(uv_async_t *main_callback) :
  Thread("worker thread", main_callback),
  platform{WorkerPlatform::for_worker(this)}
{
  //
}

// Definition must be here to see the full definition of WorkerPlatform.
WorkerThread::~WorkerThread() = default;

Result<> WorkerThread::wake()
{
  if (!is_healthy()) return health_err_result();

  return platform->wake();
}

Result<> WorkerThread::body()
{
  return platform->listen();
}

Result<Thread::CommandOutcome> WorkerThread::handle_add_command(const CommandPayload *payload)
{
  Result<bool> r = platform->handle_add_command(
    payload->get_id(), payload->get_channel_id(), payload->get_root(), payload->get_recursive());
  return r.propagate(r.get_value() ? ACK : NOTHING);
}

Result<Thread::CommandOutcome> WorkerThread::handle_remove_command(const CommandPayload *payload)
{
  Result<bool> r = platform->handle_remove_command(payload->get_id(), payload->get_channel_id());
  return r.propagate(r.get_value() ? ACK : NOTHING);
}

void WorkerThread::collect_status(Status &status)
{
  status.worker_thread_state = state_name();
  status.worker_thread_ok = get_error();
  status.worker_in_size = get_in_queue_size();
  status.worker_in_ok = get_in_queue_error();
  status.worker_out_size = get_out_queue_size();
  status.worker_out_ok = get_out_queue_error();
}
<|endoftext|>


<commit_before>// Copyright 2016 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
/**
 * @author  Peter Boros
 * @date    2004/08/20
 * @version $Id$
 * @file    segmenter.cpp
 * @brief   Query segmenter based on %FSA (%Finite %State %Automaton) (implementation)
 *
 */

#ifdef HAVE_CONFIG_H
#include "config.h"
#endif

#include "segmenter.h"

namespace fsa {

Segmenter::Segments::Segments()
      : _text(), _segments(), _map(),
        _segmentation(Segmenter::SEGMENTATION_METHODS,NULL)
{}

Segmenter::Segments::~Segments()
{
  clear();
}

void
Segmenter::Segments::clear()
{
  _segments.clear();
  _map.init(_text.size());
  initSingles();
  for(unsigned int i=0;i<SEGMENTATION_METHODS;i++){
    delete _segmentation[i];
    _segmentation[i] = nullptr;
  }
}

// {{{ Segmenter::Segments::initSingles

void Segmenter::Segments::initSingles()
{
  for(unsigned int i=0;i<_text.size();i++){
    if(!_map.isValid(i,i+1)){
      _map.set(i,i+1,_segments.size());
      _segments.push_back(Segment(i,i+1,0));
    }
  }
}

// }}}
// {{{ Segmenter::Segments::buildSegmentation

void Segmenter::Segments::buildSegmentation(Segmenter::SegmentationMethod method)
{
  int i,j;
  int n_txt=(int)_text.size(), n_sgm=_segments.size();
  int id,bestid;
  int pos, next=n_txt;
  unsigned int maxsc,conn;
  int bestval,temp=0,bias;
  std::vector<int> nextid(n_sgm,-1);
  std::vector<unsigned int> maxScore(n_sgm,0);

  if(_segmentation[method]==NULL){
    _segmentation[method] = new Segmenter::Segmentation;
  }
  else {
    _segmentation[method]->clear();
  }

  bias=0;
  switch(method){
  case SEGMENTATION_WEIGHTED_BIAS100:
    bias+=50;
  case SEGMENTATION_WEIGHTED_BIAS50:
    bias+=30;
  case SEGMENTATION_WEIGHTED_BIAS20:
    bias+=10;
  case SEGMENTATION_WEIGHTED_BIAS10:
    bias+=10;
  case SEGMENTATION_WEIGHTED:
    bestid=-1;
    for(i=n_txt;i>=0;i--){
      bestid=-1;maxsc=0;
      for(j=i+1;j<=n_txt;j++){
        id=_map.get(i,j);
        if(id>=0 && maxScore[id]+1>maxsc) {
          bestid=id;
          maxsc=maxScore[id]+1;
        }
      }
      if(maxsc>0) maxsc--;
      for(j=0;j<i;j++){
        id=_map.get(j,i);
        if(id>=0){
          nextid[id] = bestid;
          conn = _segments[id].conn();
          if(i-j<=1){
            maxScore[id] = maxsc;
          }
          else if(bias>0){
            maxScore[id] = maxsc + ((100+(i-j-2)*bias)*conn)/100;
          }
          else{
            maxScore[id] = maxsc + conn;
          }
        }
      }
    }
    id = bestid;
    while(id!=-1){
      _segmentation[method]->push_back(id);
      id=nextid[id];
    }
    break;
  case SEGMENTATION_LEFTMOST_LONGEST:
  case SEGMENTATION_LEFTMOST_WEIGHTED:
    pos = 0;
    while(pos<n_txt){
      bestid = -1; bestval = -1;
      for(i=pos+1;i<=n_txt;i++){
        id = _map.get(pos,i);
        if(id>=0 &&
           (method==SEGMENTATION_LEFTMOST_LONGEST ||
            (temp=(_segments[id].len()>1)?(int)_segments[id].conn():0)>bestval) ){
          bestid = id;
          bestval = temp;
          next = i;
        }
      }
      _segmentation[method]->push_back(bestid);
      pos=next;
    }
    break;
  case SEGMENTATION_RIGHTMOST_LONGEST:
  case SEGMENTATION_RIGHTMOST_WEIGHTED:
    pos = n_txt;
    while(pos>0){
      bestid = -1; bestval = -1;
      for(i=pos-1;i>=0;i--){
        id = _map.get(i,pos);
        if(id>=0 &&
           (method==SEGMENTATION_RIGHTMOST_LONGEST ||
            (temp=(_segments[id].len()>1)?(int)_segments[id].conn():0)>bestval) ){
          bestid = id;
          bestval = temp;
          next = i;
        }
      }
      _segmentation[method]->push_front(bestid);
      pos=next;
    }
    break;
  case SEGMENTATION_LONGEST_WEIGHTED:
  case SEGMENTATION_LONGEST_LEFTMOST:
  case SEGMENTATION_LONGEST_RIGHTMOST:
  case SEGMENTATION_WEIGHTED_LONGEST:
  case SEGMENTATION_WEIGHTED_LEFTMOST:
  case SEGMENTATION_WEIGHTED_RIGHTMOST:
    buildSegmentationRecursive(method,*_segmentation[method],0,n_txt);
    break;
  default:
    break;
  }
}

// }}}
// {{{ Segmenter::Segments::buildSegmentationRecursive

void Segmenter::Segments::buildSegmentationRecursive(Segmenter::SegmentationMethod method,
                                                     Segmenter::Segmentation& segmentation,
                                                     unsigned int beg,
                                                     unsigned int end)
{
  int bestid, bestval1, bestval2, temp;
  int i;

  // locate the best segment according to method
  bestid=-1;bestval1=-1;bestval2=-1;
  for(i=0;i<(int)_segments.size();i++){
    if(beg<=_segments[i].beg() && end>=_segments[i].end()){
      switch(method){
      case SEGMENTATION_LONGEST_WEIGHTED:
        if((int)_segments[i].len()>bestval1 ||
           ((int)_segments[i].len()==bestval1 && (int)_segments[i].conn()>bestval2) ){
          bestid=i;
          bestval1=_segments[i].len();
          bestval2=_segments[i].conn();
        }
        break;
      case SEGMENTATION_LONGEST_LEFTMOST:
        if((int)_segments[i].len()>bestval1 ||
           ((int)_segments[i].len()==bestval1 && (int)_segments[i].beg()<bestval2) ){
          bestid=i;
          bestval1=_segments[i].len();
          bestval2=_segments[i].beg();
        }
        break;
      case SEGMENTATION_LONGEST_RIGHTMOST:
        if((int)_segments[i].len()>bestval1 ||
           ((int)_segments[i].len()==bestval1 && (int)_segments[i].end()>bestval2) ){
          bestid=i;
          bestval1=_segments[i].len();
          bestval2=_segments[i].end();
        }
        break;
      case SEGMENTATION_WEIGHTED_LONGEST:
        temp = (_segments[i].len()>1)?(int)_segments[i].conn():0;
        if(temp>bestval1 ||
           (temp==bestval1 &&
            (int)_segments[i].len()>bestval2) ){
          bestid=i;
          bestval1=temp;
          bestval2=_segments[i].len();
        }
        break;
      case SEGMENTATION_WEIGHTED_LEFTMOST:
        temp = (_segments[i].len()>1)?(int)_segments[i].conn():0;
        if(temp>bestval1 ||
           (temp==bestval1 &&
            (int)_segments[i].beg()<bestval2) ){
          bestid=i;
          bestval1=temp;
          bestval2=_segments[i].beg();
        }
        break;
      case SEGMENTATION_WEIGHTED_RIGHTMOST:
        temp = (int)_segments[i].len()>1?(int)_segments[i].conn():0;
        if(temp>bestval1 ||
           (temp==bestval1 &&
            (int)_segments[i].end()>bestval2) ){
          bestid=i;
          bestval1=temp;
          bestval2=_segments[i].end();
        }
        break;
      default: // dummy defult pick first possible
        if(bestid<0){
          bestid=i;
        }
        break;
      }
    }
  }
  if(bestid<0) {
    return; // this should never happen, as all one-word segments are created
  }

  // check left side
  if(beg<_segments[bestid].beg()){
    buildSegmentationRecursive(method,segmentation,beg,_segments[bestid].beg());
  }

  // add segment
  segmentation.push_back(bestid);

  // check right side
  if(end>_segments[bestid].end()){
    buildSegmentationRecursive(method,segmentation,_segments[bestid].end(),end);
  }
}

// }}}

// {{{ Segmenter::segment

void Segmenter::segment(Segmenter::Segments &segments) const
{
  segments.clear();
  _detector.detect(segments.getText(),segments);
}

void Segmenter::segment(const NGram &text, Segmenter::Segments &segments) const
{
  segments.setText(text);
  _detector.detect(segments.getText(),segments);
}

void Segmenter::segment(const std::string &text, Segmenter::Segments &segments) const
{

  segments.setText(text);
  _detector.detect(segments.getText(),segments);
}

void Segmenter::segment(const char *text, Segmenter::Segments &segments) const
{
  segments.setText(text);
  _detector.detect(segments.getText(),segments);
}

// }}}

} // namespace fsa
<commit_msg>Unify indentation to existing style.<commit_after>// Copyright 2016 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
/**
 * @author  Peter Boros
 * @date    2004/08/20
 * @version $Id$
 * @file    segmenter.cpp
 * @brief   Query segmenter based on %FSA (%Finite %State %Automaton) (implementation)
 *
 */

#ifdef HAVE_CONFIG_H
#include "config.h"
#endif

#include "segmenter.h"

namespace fsa {

Segmenter::Segments::Segments()
  : _text(), _segments(), _map(),
    _segmentation(Segmenter::SEGMENTATION_METHODS,NULL)
{ }

Segmenter::Segments::~Segments()
{
  clear();
}

void
Segmenter::Segments::clear()
{
  _segments.clear();
  _map.init(_text.size());
  initSingles();
  for(unsigned int i=0;i<SEGMENTATION_METHODS;i++){
    delete _segmentation[i];
    _segmentation[i] = nullptr;
  }
}

// {{{ Segmenter::Segments::initSingles

void Segmenter::Segments::initSingles()
{
  for(unsigned int i=0;i<_text.size();i++){
    if(!_map.isValid(i,i+1)){
      _map.set(i,i+1,_segments.size());
      _segments.push_back(Segment(i,i+1,0));
    }
  }
}

// }}}
// {{{ Segmenter::Segments::buildSegmentation

void Segmenter::Segments::buildSegmentation(Segmenter::SegmentationMethod method)
{
  int i,j;
  int n_txt=(int)_text.size(), n_sgm=_segments.size();
  int id,bestid;
  int pos, next=n_txt;
  unsigned int maxsc,conn;
  int bestval,temp=0,bias;
  std::vector<int> nextid(n_sgm,-1);
  std::vector<unsigned int> maxScore(n_sgm,0);

  if(_segmentation[method]==NULL){
    _segmentation[method] = new Segmenter::Segmentation;
  }
  else {
    _segmentation[method]->clear();
  }

  bias=0;
  switch(method){
  case SEGMENTATION_WEIGHTED_BIAS100:
    bias+=50;
  case SEGMENTATION_WEIGHTED_BIAS50:
    bias+=30;
  case SEGMENTATION_WEIGHTED_BIAS20:
    bias+=10;
  case SEGMENTATION_WEIGHTED_BIAS10:
    bias+=10;
  case SEGMENTATION_WEIGHTED:
    bestid=-1;
    for(i=n_txt;i>=0;i--){
      bestid=-1;maxsc=0;
      for(j=i+1;j<=n_txt;j++){
        id=_map.get(i,j);
        if(id>=0 && maxScore[id]+1>maxsc) {
          bestid=id;
          maxsc=maxScore[id]+1;
        }
      }
      if(maxsc>0) maxsc--;
      for(j=0;j<i;j++){
        id=_map.get(j,i);
        if(id>=0){
          nextid[id] = bestid;
          conn = _segments[id].conn();
          if(i-j<=1){
            maxScore[id] = maxsc;
          }
          else if(bias>0){
            maxScore[id] = maxsc + ((100+(i-j-2)*bias)*conn)/100;
          }
          else{
            maxScore[id] = maxsc + conn;
          }
        }
      }
    }
    id = bestid;
    while(id!=-1){
      _segmentation[method]->push_back(id);
      id=nextid[id];
    }
    break;
  case SEGMENTATION_LEFTMOST_LONGEST:
  case SEGMENTATION_LEFTMOST_WEIGHTED:
    pos = 0;
    while(pos<n_txt){
      bestid = -1; bestval = -1;
      for(i=pos+1;i<=n_txt;i++){
        id = _map.get(pos,i);
        if(id>=0 &&
           (method==SEGMENTATION_LEFTMOST_LONGEST ||
            (temp=(_segments[id].len()>1)?(int)_segments[id].conn():0)>bestval) ){
          bestid = id;
          bestval = temp;
          next = i;
        }
      }
      _segmentation[method]->push_back(bestid);
      pos=next;
    }
    break;
  case SEGMENTATION_RIGHTMOST_LONGEST:
  case SEGMENTATION_RIGHTMOST_WEIGHTED:
    pos = n_txt;
    while(pos>0){
      bestid = -1; bestval = -1;
      for(i=pos-1;i>=0;i--){
        id = _map.get(i,pos);
        if(id>=0 &&
           (method==SEGMENTATION_RIGHTMOST_LONGEST ||
            (temp=(_segments[id].len()>1)?(int)_segments[id].conn():0)>bestval) ){
          bestid = id;
          bestval = temp;
          next = i;
        }
      }
      _segmentation[method]->push_front(bestid);
      pos=next;
    }
    break;
  case SEGMENTATION_LONGEST_WEIGHTED:
  case SEGMENTATION_LONGEST_LEFTMOST:
  case SEGMENTATION_LONGEST_RIGHTMOST:
  case SEGMENTATION_WEIGHTED_LONGEST:
  case SEGMENTATION_WEIGHTED_LEFTMOST:
  case SEGMENTATION_WEIGHTED_RIGHTMOST:
    buildSegmentationRecursive(method,*_segmentation[method],0,n_txt);
    break;
  default:
    break;
  }
}

// }}}
// {{{ Segmenter::Segments::buildSegmentationRecursive

void Segmenter::Segments::buildSegmentationRecursive(Segmenter::SegmentationMethod method,
                                                     Segmenter::Segmentation& segmentation,
                                                     unsigned int beg,
                                                     unsigned int end)
{
  int bestid, bestval1, bestval2, temp;
  int i;

  // locate the best segment according to method
  bestid=-1;bestval1=-1;bestval2=-1;
  for(i=0;i<(int)_segments.size();i++){
    if(beg<=_segments[i].beg() && end>=_segments[i].end()){
      switch(method){
      case SEGMENTATION_LONGEST_WEIGHTED:
        if((int)_segments[i].len()>bestval1 ||
           ((int)_segments[i].len()==bestval1 && (int)_segments[i].conn()>bestval2) ){
          bestid=i;
          bestval1=_segments[i].len();
          bestval2=_segments[i].conn();
        }
        break;
      case SEGMENTATION_LONGEST_LEFTMOST:
        if((int)_segments[i].len()>bestval1 ||
           ((int)_segments[i].len()==bestval1 && (int)_segments[i].beg()<bestval2) ){
          bestid=i;
          bestval1=_segments[i].len();
          bestval2=_segments[i].beg();
        }
        break;
      case SEGMENTATION_LONGEST_RIGHTMOST:
        if((int)_segments[i].len()>bestval1 ||
           ((int)_segments[i].len()==bestval1 && (int)_segments[i].end()>bestval2) ){
          bestid=i;
          bestval1=_segments[i].len();
          bestval2=_segments[i].end();
        }
        break;
      case SEGMENTATION_WEIGHTED_LONGEST:
        temp = (_segments[i].len()>1)?(int)_segments[i].conn():0;
        if(temp>bestval1 ||
           (temp==bestval1 &&
            (int)_segments[i].len()>bestval2) ){
          bestid=i;
          bestval1=temp;
          bestval2=_segments[i].len();
        }
        break;
      case SEGMENTATION_WEIGHTED_LEFTMOST:
        temp = (_segments[i].len()>1)?(int)_segments[i].conn():0;
        if(temp>bestval1 ||
           (temp==bestval1 &&
            (int)_segments[i].beg()<bestval2) ){
          bestid=i;
          bestval1=temp;
          bestval2=_segments[i].beg();
        }
        break;
      case SEGMENTATION_WEIGHTED_RIGHTMOST:
        temp = (int)_segments[i].len()>1?(int)_segments[i].conn():0;
        if(temp>bestval1 ||
           (temp==bestval1 &&
            (int)_segments[i].end()>bestval2) ){
          bestid=i;
          bestval1=temp;
          bestval2=_segments[i].end();
        }
        break;
      default: // dummy defult pick first possible
        if(bestid<0){
          bestid=i;
        }
        break;
      }
    }
  }
  if(bestid<0) {
    return; // this should never happen, as all one-word segments are created
  }

  // check left side
  if(beg<_segments[bestid].beg()){
    buildSegmentationRecursive(method,segmentation,beg,_segments[bestid].beg());
  }

  // add segment
  segmentation.push_back(bestid);

  // check right side
  if(end>_segments[bestid].end()){
    buildSegmentationRecursive(method,segmentation,_segments[bestid].end(),end);
  }
}

// }}}

// {{{ Segmenter::segment

void Segmenter::segment(Segmenter::Segments &segments) const
{
  segments.clear();
  _detector.detect(segments.getText(),segments);
}

void Segmenter::segment(const NGram &text, Segmenter::Segments &segments) const
{
  segments.setText(text);
  _detector.detect(segments.getText(),segments);
}

void Segmenter::segment(const std::string &text, Segmenter::Segments &segments) const
{

  segments.setText(text);
  _detector.detect(segments.getText(),segments);
}

void Segmenter::segment(const char *text, Segmenter::Segments &segments) const
{
  segments.setText(text);
  _detector.detect(segments.getText(),segments);
}

// }}}

} // namespace fsa
<|endoftext|>


<commit_before>/*
 *  Copyright (c) 2015, Nagoya University

 *  All rights reserved.
 *
 *  Redistribution and use in source and binary forms, with or without
 *  modification, are permitted provided that the following conditions are met:
 *
 *  * Redistributions of source code must retain the above copyright notice, this
 *    list of conditions and the following disclaimer.
 *
 *  * Redistributions in binary form must reproduce the above copyright notice,
 *    this list of conditions and the following disclaimer in the documentation
 *    and/or other materials provided with the distribution.
 *
 *  * Neither the name of Autoware nor the names of its
 *    contributors may be used to endorse or promote products derived from
 *    this software without specific prior written permission.
 *
 *  THIS SOFTWARE IS PROVIDED BY 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 COPYRIGHT HOLDER 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 "lane_select_core.h"

namespace lane_planner
{
// Constructor
LaneSelectNode::LaneSelectNode()
  : private_nh_("~")
  , num_of_lane_(-1)
  , num_of_closest_(-1)
  , change_flag_(ChangeFlag::unknown)
  , is_lane_array_subscribed_(false)
  , is_current_pose_subscribed_(false)
  , last_time_(ros::Time::now())
{
  initParameter();
  initSubscriber();
  initPublisher();
}

// Destructor
LaneSelectNode::~LaneSelectNode()
{
}

void LaneSelectNode::initSubscriber()
{
  // setup subscriber
  sub1_ = nh_.subscribe("traffic_waypoints_array", 100, &LaneSelectNode::callbackFromLaneArray, this);
  sub2_ = nh_.subscribe("current_pose", 100, &LaneSelectNode::callbackFromCurrentPose, this);
}

void LaneSelectNode::initPublisher()
{
  // setup publisher
  pub_ = nh_.advertise<waypoint_follower::lane>("base_waypoints", 10, true);
}

void LaneSelectNode::initParameter()
{
  private_nh_.param<int32_t>("size_of_waypoints", size_of_waypoints_, int32_t(30));
  private_nh_.param<int32_t>("lane_change_interval",lane_change_interval_,int32_t(2));
}

void LaneSelectNode::publishLocalLane()
{
  if (!is_current_pose_subscribed_ || !is_lane_array_subscribed_)
  {
    ROS_ERROR("Necessary topics are not subscribed yet.");
    return;
  }

  if (num_of_lane_ == -1)
    num_of_lane_++;

  ros::Time current_time = ros::Time::now();
  double dt = (current_time -last_time_).toSec();
  ROS_INFO("dt: %lf",dt);
  if (dt > 1.0 && (change_flag_ == ChangeFlag::right && num_of_lane_ < static_cast<int32_t>(lane_array_.lanes.size())))
  {
    num_of_lane_++;
    last_time_ = current_time;
  }

  if (dt > 1.0 && (change_flag_ == ChangeFlag::left && num_of_lane_ > 0))
  {
    num_of_lane_--;
    last_time_ = current_time;
  }

  waypoint_follower::lane local_lane;
  createLocalLane(&local_lane);
  pub_.publish(local_lane);

  //if (current_lane.waypoints.at(num_of_closest_).change_flag == static_cast<ChangeFlagInteger>(ChangeFlag::right) &&
   //   num_of_lane_ != lane_array_.size() - 1)
  //{
  //  num_of_lane_++;
  //}

  is_current_pose_subscribed_ = false;
}

void LaneSelectNode::createLocalLane(waypoint_follower::lane *lane)
{
  num_of_closest_ = getClosestWaypoint(lane_array_.lanes.at(num_of_lane_), current_pose_.pose);

  if (num_of_closest_ == -1)
  {
    ROS_ERROR("cannot get closest waypoint");
    return;
  }

  // setup
  lane->header.stamp = ros::Time::now();
  lane->header.frame_id = "map";

  // push some waypoints
  for (auto i = 0; i < size_of_waypoints_; i++)
  {
    if(num_of_closest_ + i > static_cast<int32_t>(lane_array_.lanes.at(num_of_lane_).waypoints.size() -1) )
      break;

    lane->waypoints.push_back(lane_array_.lanes.at(num_of_lane_).waypoints.at(num_of_closest_ + i));

  }

  // push current_pose as first waypoint
  waypoint_follower::waypoint first_waypoint;
  first_waypoint = lane->waypoints.at(0);
  first_waypoint.pose.pose.position.x = current_pose_.pose.position.x;
  first_waypoint.pose.pose.position.y = current_pose_.pose.position.y;
  auto it = lane->waypoints.begin();
  lane->waypoints.insert(it,first_waypoint);
  change_flag_ = static_cast<ChangeFlag>(lane_array_.lanes.at(num_of_lane_).waypoints.at(num_of_closest_).change_flag);
  ROS_INFO("change_flag: %d", static_cast<ChangeFlagInteger>(change_flag_));

}

void LaneSelectNode::callbackFromLaneArray(const waypoint_follower::LaneArrayConstPtr &msg)
{
  lane_array_ = *msg;
  is_lane_array_subscribed_ = true;
}

void LaneSelectNode::callbackFromCurrentPose(const geometry_msgs::PoseStampedConstPtr &msg)
{
  current_pose_ = *msg;
  is_current_pose_subscribed_ = true;
  publishLocalLane();
}

// get closest waypoint from current pose
/*int32_t getClosestWaypoint(const waypoint_follower::lane &current_path, const geometry_msgs::Pose &current_pose)
{
  WayPoints wp;
  wp.setPath(current_path);

  if (wp.isEmpty())
    return -1;

  // search closest candidate within a certain meter
  double search_distance = 5.0;
  std::vector<int> waypoint_candidates;
  for (int i = 1; i < wp.getSize(); i++)
  {
    if (getPlaneDistance(wp.getWaypointPosition(i), current_pose.position) > search_distance)
      continue;

    if (!wp.isFront(i, current_pose))
      continue;

    double angle_threshold = 90;
    if (getRelativeAngle(wp.getWaypointPose(i), current_pose) > angle_threshold)
      continue;

    waypoint_candidates.push_back(i);
  }

  // get closest waypoint from candidates
  if (!waypoint_candidates.empty())
  {
    int waypoint_min = -1;
    double distance_min = DBL_MAX;
    for (auto el : waypoint_candidates)
    {
      // ROS_INFO("closest_candidates : %d",el);
      double d = getPlaneDistance(wp.getWaypointPosition(el), current_pose.position);
      if (d < distance_min)
      {
        waypoint_min = el;
        distance_min = d;
      }
    }
    return waypoint_min;
  }
  else
  {
    ROS_INFO("no candidate. search closest waypoint from all waypoints...");
    // if there is no candidate...
    int waypoint_min = -1;
    double distance_min = DBL_MAX;
    for (int i = 1; i < wp.getSize(); i++)
    {
      if (!wp.isFront(i, current_pose))
        continue;

      // if (!wp.isValid(i, current_pose))
      //  continue;

      double d = getPlaneDistance(wp.getWaypointPosition(i), current_pose.position);
      if (d < distance_min)
      {
        waypoint_min = i;
        distance_min = d;
      }
    }
    return waypoint_min;
  }
}*/

}  // lane_planner
<commit_msg>apply clang-format<commit_after>/*
 *  Copyright (c) 2015, Nagoya University

 *  All rights reserved.
 *
 *  Redistribution and use in source and binary forms, with or without
 *  modification, are permitted provided that the following conditions are met:
 *
 *  * Redistributions of source code must retain the above copyright notice, this
 *    list of conditions and the following disclaimer.
 *
 *  * Redistributions in binary form must reproduce the above copyright notice,
 *    this list of conditions and the following disclaimer in the documentation
 *    and/or other materials provided with the distribution.
 *
 *  * Neither the name of Autoware nor the names of its
 *    contributors may be used to endorse or promote products derived from
 *    this software without specific prior written permission.
 *
 *  THIS SOFTWARE IS PROVIDED BY 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 COPYRIGHT HOLDER 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 "lane_select_core.h"

namespace lane_planner
{
// Constructor
LaneSelectNode::LaneSelectNode()
  : private_nh_("~")
  , num_of_lane_(-1)
  , num_of_closest_(-1)
  , change_flag_(ChangeFlag::unknown)
  , is_lane_array_subscribed_(false)
  , is_current_pose_subscribed_(false)
  , last_time_(ros::Time::now())
{
  initParameter();
  initSubscriber();
  initPublisher();
}

// Destructor
LaneSelectNode::~LaneSelectNode()
{
}

void LaneSelectNode::initSubscriber()
{
  // setup subscriber
  sub1_ = nh_.subscribe("traffic_waypoints_array", 100, &LaneSelectNode::callbackFromLaneArray, this);
  sub2_ = nh_.subscribe("current_pose", 100, &LaneSelectNode::callbackFromCurrentPose, this);
}

void LaneSelectNode::initPublisher()
{
  // setup publisher
  pub_ = nh_.advertise<waypoint_follower::lane>("base_waypoints", 10, true);
}

void LaneSelectNode::initParameter()
{
  private_nh_.param<int32_t>("size_of_waypoints", size_of_waypoints_, int32_t(30));
  private_nh_.param<int32_t>("lane_change_interval", lane_change_interval_, int32_t(2));
}

void LaneSelectNode::publishLocalLane()
{
  if (!is_current_pose_subscribed_ || !is_lane_array_subscribed_)
  {
    ROS_ERROR("Necessary topics are not subscribed yet.");
    return;
  }

  if (num_of_lane_ == -1)
    num_of_lane_++;

  ros::Time current_time = ros::Time::now();
  double dt = (current_time - last_time_).toSec();
  ROS_INFO("dt: %lf", dt);
  if (dt > 1.0 && (change_flag_ == ChangeFlag::right && num_of_lane_ < static_cast<int32_t>(lane_array_.lanes.size())))
  {
    num_of_lane_++;
    last_time_ = current_time;
  }

  if (dt > 1.0 && (change_flag_ == ChangeFlag::left && num_of_lane_ > 0))
  {
    num_of_lane_--;
    last_time_ = current_time;
  }

  waypoint_follower::lane local_lane;
  createLocalLane(&local_lane);
  pub_.publish(local_lane);

  // if (current_lane.waypoints.at(num_of_closest_).change_flag == static_cast<ChangeFlagInteger>(ChangeFlag::right) &&
  //   num_of_lane_ != lane_array_.size() - 1)
  //{
  //  num_of_lane_++;
  //}

  is_current_pose_subscribed_ = false;
}

void LaneSelectNode::createLocalLane(waypoint_follower::lane *lane)
{
  num_of_closest_ = getClosestWaypoint(lane_array_.lanes.at(num_of_lane_), current_pose_.pose);

  if (num_of_closest_ == -1)
  {
    ROS_ERROR("cannot get closest waypoint");
    return;
  }

  // setup
  lane->header.stamp = ros::Time::now();
  lane->header.frame_id = "map";

  // push some waypoints
  for (auto i = 0; i < size_of_waypoints_; i++)
  {
    if (num_of_closest_ + i > static_cast<int32_t>(lane_array_.lanes.at(num_of_lane_).waypoints.size() - 1))
      break;

    lane->waypoints.push_back(lane_array_.lanes.at(num_of_lane_).waypoints.at(num_of_closest_ + i));
  }

  // push current_pose as first waypoint
  waypoint_follower::waypoint first_waypoint;
  first_waypoint = lane->waypoints.at(0);
  first_waypoint.pose.pose.position.x = current_pose_.pose.position.x;
  first_waypoint.pose.pose.position.y = current_pose_.pose.position.y;
  auto it = lane->waypoints.begin();
  lane->waypoints.insert(it, first_waypoint);
  change_flag_ = static_cast<ChangeFlag>(lane_array_.lanes.at(num_of_lane_).waypoints.at(num_of_closest_).change_flag);
  ROS_INFO("change_flag: %d", static_cast<ChangeFlagInteger>(change_flag_));
}

void LaneSelectNode::callbackFromLaneArray(const waypoint_follower::LaneArrayConstPtr &msg)
{
  lane_array_ = *msg;
  is_lane_array_subscribed_ = true;
}

void LaneSelectNode::callbackFromCurrentPose(const geometry_msgs::PoseStampedConstPtr &msg)
{
  current_pose_ = *msg;
  is_current_pose_subscribed_ = true;
  publishLocalLane();
}

// get closest waypoint from current pose
/*int32_t getClosestWaypoint(const waypoint_follower::lane &current_path, const geometry_msgs::Pose &current_pose)
{
  WayPoints wp;
  wp.setPath(current_path);

  if (wp.isEmpty())
    return -1;

  // search closest candidate within a certain meter
  double search_distance = 5.0;
  std::vector<int> waypoint_candidates;
  for (int i = 1; i < wp.getSize(); i++)
  {
    if (getPlaneDistance(wp.getWaypointPosition(i), current_pose.position) > search_distance)
      continue;

    if (!wp.isFront(i, current_pose))
      continue;

    double angle_threshold = 90;
    if (getRelativeAngle(wp.getWaypointPose(i), current_pose) > angle_threshold)
      continue;

    waypoint_candidates.push_back(i);
  }

  // get closest waypoint from candidates
  if (!waypoint_candidates.empty())
  {
    int waypoint_min = -1;
    double distance_min = DBL_MAX;
    for (auto el : waypoint_candidates)
    {
      // ROS_INFO("closest_candidates : %d",el);
      double d = getPlaneDistance(wp.getWaypointPosition(el), current_pose.position);
      if (d < distance_min)
      {
        waypoint_min = el;
        distance_min = d;
      }
    }
    return waypoint_min;
  }
  else
  {
    ROS_INFO("no candidate. search closest waypoint from all waypoints...");
    // if there is no candidate...
    int waypoint_min = -1;
    double distance_min = DBL_MAX;
    for (int i = 1; i < wp.getSize(); i++)
    {
      if (!wp.isFront(i, current_pose))
        continue;

      // if (!wp.isValid(i, current_pose))
      //  continue;

      double d = getPlaneDistance(wp.getWaypointPosition(i), current_pose.position);
      if (d < distance_min)
      {
        waypoint_min = i;
        distance_min = d;
      }
    }
    return waypoint_min;
  }
}*/

}  // lane_planner
<|endoftext|>


<commit_before>/*************************************************************************
 *
 * Copyright (c) 2011-2012 Kohei Yoshida
 *
 * Permission is hereby granted, free of charge, to any person
 * obtaining a copy of this software and associated documentation
 * files (the "Software"), to deal in the Software without
 * restriction, including without limitation the rights to use,
 * copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the
 * Software is furnished to do so, subject to the following
 * conditions:
 *
 * The above copyright notice and this permission notice shall be
 * included in all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
 * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
 * OTHER DEALINGS IN THE SOFTWARE.
 *
 ************************************************************************/

#ifndef __MDDS_GRID_MAP_COLUMN_HPP__
#define __MDDS_GRID_MAP_COLUMN_HPP__

#include "default_deleter.hpp"
#include "compat/unique_ptr.hpp"
#include "global.hpp"
#include "grid_map_types.hpp"

#include <vector>
#include <algorithm>
#include <cassert>

#include <boost/noncopyable.hpp>

namespace mdds { namespace __gridmap {

/**
 * Each column consists of a series of blocks, and each block stores a
 * series of non-empty cells of identical type.
 */
template<typename _Trait>
class column
{
public:
    typedef size_t size_type;

    typedef typename mdds::gridmap::base_cell_block cell_block_type;
    typedef typename mdds::gridmap::cell_t cell_category_type;
    typedef typename _Trait::row_key_type row_key_type;

private:
    typedef _Trait trait;

    typedef typename _Trait::cell_block_func cell_block_func;

    struct block : boost::noncopyable
    {
        size_type m_size;
        cell_block_type* mp_data;

        block();
        block(size_type _size);
        block(const block& other);
        ~block();
    };

public:
    column();
    column(size_type init_row_size);
    column(const column& other);
    ~column();

    template<typename _T>
    void set_cell(row_key_type row, const _T& cell);

    template<typename _T>
    void set_cells(row_key_type row, const _T& it_begin, const _T& it_end);

    template<typename _T>
    void insert_cells(row_key_type row, const _T& it_begin, const _T& it_end);

    template<typename _T>
    void get_cell(row_key_type row, _T& cell) const;

    template<typename _T>
    _T get_cell(row_key_type row) const;

    bool is_empty(row_key_type row) const;

    void set_empty(row_key_type start_row, row_key_type end_row);

    void erase(row_key_type start_row, row_key_type end_row);

    void insert_empty(row_key_type row, size_type length);

    void clear();

    size_type size() const;

    size_type block_size() const;

    bool empty() const;

    void resize(size_type new_size);

    void swap(column& other);

    bool operator== (const column& other) const;
    bool operator!= (const column& other) const;

    column& operator= (const column& other);

    template<typename _T>
    static gridmap::cell_t get_cell_type(const _T& cell);

private:
    /**
     * Check the row value to make sure it's within specified range, and
     * convert it to size_type for internal use.
     */
    size_type check_row_range(row_key_type row) const;

    void get_block_position(
        size_type row, size_type& start_row, size_type& block_index, size_type start_block=0, size_type start_block_row=0) const;

    template<typename _T>
    void create_new_block_with_new_cell(cell_block_type*& data, const _T& cell);

    template<typename _T>
    void set_cell_to_middle_of_block(
        size_type block_index, size_type pos_in_block, const _T& cell);

    template<typename _T>
    void append_cell_to_block(size_type block_index, const _T& cell);

    template<typename _T>
    void set_cell_impl(size_type row, const _T& cell);

    template<typename _T>
    void set_cell_to_empty_block(
        size_type block_index, size_type pos_in_block, const _T& cell);

    template<typename _T>
    void set_cell_to_block_of_size_one(
        size_type block_index, const _T& cell);

    template<typename _T>
    void set_cell_to_top_of_data_block(
        size_type block_index, const _T& cell);

    template<typename _T>
    void set_cell_to_bottom_of_data_block(
        size_type block_index, const _T& cell);

    void set_empty_in_single_block(
        size_type start_row, size_type end_row, size_type block_index, size_type start_row_in_block);

    void set_empty_in_multi_blocks(
        size_type start_row, size_type end_row,
        size_type block_index1, size_type start_row_in_block1,
        size_type block_index2, size_type start_row_in_block2);

    void erase_impl(size_type start_row, size_type end_row);

    void insert_empty_impl(size_type row, size_type length);

    template<typename _T>
    void set_cells_impl(size_type row, const _T& it_begin, const _T& it_end);

    template<typename _T>
    void insert_cells_impl(size_type row, const _T& it_begin, const _T& it_end);

    template<typename _T>
    void set_cells_to_single_block(
        size_type start_row, size_type end_row, size_type block_index,
        size_type start_row_in_block, const _T& it_begin, const _T& it_end);

    template<typename _T>
    void set_cells_to_multi_blocks(
        size_type start_row, size_type end_row,
        size_type block_index1, size_type start_row_in_block1,
        size_type block_index2, size_type start_row_in_block2,
        const _T& it_begin, const _T& it_end);

    template<typename _T>
    void set_cells_to_multi_blocks_block1_non_equal(
        size_type start_row, size_type end_row,
        size_type block_index1, size_type start_row_in_block1,
        size_type block_index2, size_type start_row_in_block2,
        const _T& it_begin, const _T& it_end);

    template<typename _T>
    void set_cells_to_multi_blocks_block1_non_empty(
        size_type start_row, size_type end_row,
        size_type block_index1, size_type start_row_in_block1,
        size_type block_index2, size_type start_row_in_block2,
        const _T& it_begin, const _T& it_end);

    template<typename _T>
    bool append_to_prev_block(
        size_type block_index, cell_category_type cat, size_type length,
        const _T& it_begin, const _T& it_end);

    template<typename _T>
    void insert_cells_to_middle(
        size_type row, size_type block_index, size_type start_row,
        const _T& it_begin, const _T& it_end);

private:
    typedef std::vector<block*> blocks_type;
    blocks_type m_blocks;
    size_type m_cur_size;
};

}}

#include "grid_map_column_def.inl"

#endif
<commit_msg>Method descriptions.<commit_after>/*************************************************************************
 *
 * Copyright (c) 2011-2012 Kohei Yoshida
 *
 * Permission is hereby granted, free of charge, to any person
 * obtaining a copy of this software and associated documentation
 * files (the "Software"), to deal in the Software without
 * restriction, including without limitation the rights to use,
 * copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the
 * Software is furnished to do so, subject to the following
 * conditions:
 *
 * The above copyright notice and this permission notice shall be
 * included in all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
 * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
 * OTHER DEALINGS IN THE SOFTWARE.
 *
 ************************************************************************/

#ifndef __MDDS_GRID_MAP_COLUMN_HPP__
#define __MDDS_GRID_MAP_COLUMN_HPP__

#include "default_deleter.hpp"
#include "compat/unique_ptr.hpp"
#include "global.hpp"
#include "grid_map_types.hpp"

#include <vector>
#include <algorithm>
#include <cassert>

#include <boost/noncopyable.hpp>

namespace mdds { namespace __gridmap {

/**
 * Each column consists of a series of blocks, and each block stores a
 * series of non-empty cells of identical type.
 */
template<typename _Trait>
class column
{
public:
    typedef size_t size_type;

    typedef typename mdds::gridmap::base_cell_block cell_block_type;
    typedef typename mdds::gridmap::cell_t cell_category_type;
    typedef typename _Trait::row_key_type row_key_type;

private:
    typedef _Trait trait;

    typedef typename _Trait::cell_block_func cell_block_func;

    struct block : boost::noncopyable
    {
        size_type m_size;
        cell_block_type* mp_data;

        block();
        block(size_type _size);
        block(const block& other);
        ~block();
    };

public:
    column();
    column(size_type init_row_size);
    column(const column& other);
    ~column();

    /**
     * Set a value of an arbitrary type to a specified row.  The type of the
     * value is inferred from the value passed to this method.  The new value
     * will overwrite an existing value at the specified row position if any.
     *
     *
The method will throw an std::out_of_range exception if
     * the specified row is outside the current container size.

     *
     *
Calling this method will not change the size of the container.

     *
     * @param row row to insert the value to.
     * @param cell value to insert.
     */
    template<typename _T>
    void set_cell(row_key_type row, const _T& cell);

    /**
     * Set multiple cell values of identical type to a range of cells starting
     * at specified row.  Any existing cell values will be overwritten by the
     * new values.
     *
     *
The method will throw an std::out_of_range exception if
     * the range of new values would fall outside the current container
     * size.

     *
     *
Calling this method will not change the size of the container.

     *
     * @param row position of the first value of the series of new values
     *            being inserted.
     * @param it_begin iterator that points to the begin position of the
     *                 values being set.
     * @param it_end iterator that points to the end position of the values
     *               being set.
     */
    template<typename _T>
    void set_cells(row_key_type row, const _T& it_begin, const _T& it_end);

    /**
     * Insert multiple cell values of identical type to a specified row
     * position.  Existing values that occur at or below the specified row
     * position will get shifted after the insertion.  No existing values will
     * be overwritten by the inserted values.
     *
     *
The method will throw an std::out_of_range exception if
     * the specified row position is outside the current container size.

     *
     *
Calling this method will increase the size of the container by
     * the length of the new values inserted.

     *
     * @param row row position at which the new values are to be inserted.
     * @param it_begin iterator that points to the begin position of the
     *                 values being inserted.
     * @param it_end iterator that points to the end position of the values
     *               being inserted.
     */
    template<typename _T>
    void insert_cells(row_key_type row, const _T& it_begin, const _T& it_end);

    template<typename _T>
    void get_cell(row_key_type row, _T& cell) const;

    template<typename _T>
    _T get_cell(row_key_type row) const;

    bool is_empty(row_key_type row) const;

    void set_empty(row_key_type start_row, row_key_type end_row);

    void erase(row_key_type start_row, row_key_type end_row);

    void insert_empty(row_key_type row, size_type length);

    void clear();

    size_type size() const;

    size_type block_size() const;

    bool empty() const;

    void resize(size_type new_size);

    void swap(column& other);

    bool operator== (const column& other) const;
    bool operator!= (const column& other) const;

    column& operator= (const column& other);

    template<typename _T>
    static gridmap::cell_t get_cell_type(const _T& cell);

private:
    /**
     * Check the row value to make sure it's within specified range, and
     * convert it to size_type for internal use.
     */
    size_type check_row_range(row_key_type row) const;

    void get_block_position(
        size_type row, size_type& start_row, size_type& block_index, size_type start_block=0, size_type start_block_row=0) const;

    template<typename _T>
    void create_new_block_with_new_cell(cell_block_type*& data, const _T& cell);

    template<typename _T>
    void set_cell_to_middle_of_block(
        size_type block_index, size_type pos_in_block, const _T& cell);

    template<typename _T>
    void append_cell_to_block(size_type block_index, const _T& cell);

    template<typename _T>
    void set_cell_impl(size_type row, const _T& cell);

    template<typename _T>
    void set_cell_to_empty_block(
        size_type block_index, size_type pos_in_block, const _T& cell);

    template<typename _T>
    void set_cell_to_block_of_size_one(
        size_type block_index, const _T& cell);

    template<typename _T>
    void set_cell_to_top_of_data_block(
        size_type block_index, const _T& cell);

    template<typename _T>
    void set_cell_to_bottom_of_data_block(
        size_type block_index, const _T& cell);

    void set_empty_in_single_block(
        size_type start_row, size_type end_row, size_type block_index, size_type start_row_in_block);

    void set_empty_in_multi_blocks(
        size_type start_row, size_type end_row,
        size_type block_index1, size_type start_row_in_block1,
        size_type block_index2, size_type start_row_in_block2);

    void erase_impl(size_type start_row, size_type end_row);

    void insert_empty_impl(size_type row, size_type length);

    template<typename _T>
    void set_cells_impl(size_type row, const _T& it_begin, const _T& it_end);

    template<typename _T>
    void insert_cells_impl(size_type row, const _T& it_begin, const _T& it_end);

    template<typename _T>
    void set_cells_to_single_block(
        size_type start_row, size_type end_row, size_type block_index,
        size_type start_row_in_block, const _T& it_begin, const _T& it_end);

    template<typename _T>
    void set_cells_to_multi_blocks(
        size_type start_row, size_type end_row,
        size_type block_index1, size_type start_row_in_block1,
        size_type block_index2, size_type start_row_in_block2,
        const _T& it_begin, const _T& it_end);

    template<typename _T>
    void set_cells_to_multi_blocks_block1_non_equal(
        size_type start_row, size_type end_row,
        size_type block_index1, size_type start_row_in_block1,
        size_type block_index2, size_type start_row_in_block2,
        const _T& it_begin, const _T& it_end);

    template<typename _T>
    void set_cells_to_multi_blocks_block1_non_empty(
        size_type start_row, size_type end_row,
        size_type block_index1, size_type start_row_in_block1,
        size_type block_index2, size_type start_row_in_block2,
        const _T& it_begin, const _T& it_end);

    template<typename _T>
    bool append_to_prev_block(
        size_type block_index, cell_category_type cat, size_type length,
        const _T& it_begin, const _T& it_end);

    template<typename _T>
    void insert_cells_to_middle(
        size_type row, size_type block_index, size_type start_row,
        const _T& it_begin, const _T& it_end);

private:
    typedef std::vector<block*> blocks_type;
    blocks_type m_blocks;
    size_type m_cur_size;
};

}}

#include "grid_map_column_def.inl"

#endif
<|endoftext|>


<commit_before>/*
 *  GlobalHistogramBinarizer.cpp
 *  zxing
 *
 *  Created by Ralf Kistner on 16/10/2009.
 *  Copyright 2008 ZXing authors All rights reserved.
 *  Modified by Lukasz Warchol on 02/02/2010.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include <zxing/common/GlobalHistogramBinarizer.h>

#include <zxing/common/IllegalArgumentException.h>

namespace zxing {
using namespace std;

const int LUMINANCE_BITS = 5;
const int LUMINANCE_SHIFT = 8 - LUMINANCE_BITS;
const int LUMINANCE_BUCKETS = 1 << LUMINANCE_BITS;

GlobalHistogramBinarizer::GlobalHistogramBinarizer(Ref<LuminanceSource> source) :
  Binarizer(source), cached_matrix_(NULL), cached_row_(NULL), cached_row_num_(-1) {

}

GlobalHistogramBinarizer::~GlobalHistogramBinarizer() {
}

Ref<BitArray> GlobalHistogramBinarizer::getBlackRow(int y, Ref<BitArray> row) {
  if (y == cached_row_num_) {
    return cached_row_;
  }

  vector<int> histogram(LUMINANCE_BUCKETS, 0);
  LuminanceSource& source = *getLuminanceSource();
  int width = source.getWidth();
  if (row == NULL || static_cast<int>(row->getSize()) < width) {
    row = new BitArray(width);
  } else {
    row->clear();
  }

  //TODO(flyashi): cache this instead of allocating and deleting per row
  unsigned char* row_pixels = NULL;
  try {
      row_pixels = new unsigned char[width];
      getLuminanceSource()->getRow(y,row_pixels);
      for (int x = 0; x < width; x++) {
          histogram[row_pixels[x] >> LUMINANCE_SHIFT]++;
      }
      int blackPoint = estimate(histogram) << LUMINANCE_SHIFT;

      Ref<BitArray> array_ref(new BitArray(width));
      BitArray& array = *array_ref;

      int left = row_pixels[0];
      int center = row_pixels[1];
      for (int x = 1; x < width - 1; x++) {
          int right = row_pixels[x + 1];
          // A simple -1 4 -1 box filter with a weight of 2.
          int luminance = ((center << 2) - left - right) >> 1;
          if (luminance < blackPoint) {
              array.set(x);
          }
          left = center;
          center = right;
      }

      cached_row_ = array_ref;
      cached_row_num_ = y;
      delete [] row_pixels;
      return array_ref;
  } catch (IllegalArgumentException const& iae) {
      // Cache the fact that this row failed.
      cached_row_ = NULL;
      cached_row_num_ = y;
      delete [] row_pixels;
      throw iae;
  }
}

Ref<BitMatrix> GlobalHistogramBinarizer::getBlackMatrix() {
  if (cached_matrix_ != NULL) {
    return cached_matrix_;
  }

  // Faster than working with the reference
  LuminanceSource& source = *getLuminanceSource();
  int width = source.getWidth();
  int height = source.getHeight();
  vector<int> histogram(LUMINANCE_BUCKETS, 0);

  // Quickly calculates the histogram by sampling four rows from the image.
  // This proved to be more robust on the blackbox tests than sampling a
  // diagonal as we used to do.
  unsigned char* row = new unsigned char[width];
  for (int y = 1; y < 5; y++) {
    int rownum = height * y / 5;
    int right = (width << 2) / 5;
    int sdf;
    getLuminanceSource()->getRow(rownum,row);
    for (int x = width / 5; x < right; x++) {
      histogram[row[x] >> LUMINANCE_SHIFT]++;
      sdf = histogram[row[x] >> LUMINANCE_SHIFT];
    }
  }

  int blackPoint = estimate(histogram) << LUMINANCE_SHIFT;

  Ref<BitMatrix> matrix_ref(new BitMatrix(width, height));
  BitMatrix& matrix = *matrix_ref;
  for (int y = 0; y < height; y++) {
    getLuminanceSource()->getRow(y,row);
    for (int x = 0; x < width; x++) {
      if (row[x] <= blackPoint)
        matrix.set(x, y);
    }
  }

  cached_matrix_ = matrix_ref;

  delete [] row;
  return matrix_ref;
}

int GlobalHistogramBinarizer::estimate(vector<int> &histogram) {
  int numBuckets = histogram.size();
  int maxBucketCount = 0;

  // Find tallest peak in histogram
  int firstPeak = 0;
  int firstPeakSize = 0;
  for (int i = 0; i < numBuckets; i++) {
    if (histogram[i] > firstPeakSize) {
      firstPeak = i;
      firstPeakSize = histogram[i];
    }
    if (histogram[i] > maxBucketCount) {
      maxBucketCount = histogram[i];
    }
  }

  // Find second-tallest peak -- well, another peak that is tall and not
  // so close to the first one
  int secondPeak = 0;
  int secondPeakScore = 0;
  for (int i = 0; i < numBuckets; i++) {
    int distanceToBiggest = i - firstPeak;
    // Encourage more distant second peaks by multiplying by square of distance
    int score = histogram[i] * distanceToBiggest * distanceToBiggest;
    if (score > secondPeakScore) {
      secondPeak = i;
      secondPeakScore = score;
    }
  }

  // Put firstPeak first
  if (firstPeak > secondPeak) {
    int temp = firstPeak;
    firstPeak = secondPeak;
    secondPeak = temp;
  }

  // Kind of arbitrary; if the two peaks are very close, then we figure there is
  // so little dynamic range in the image, that discriminating black and white
  // is too error-prone.
  // Decoding the image/line is either pointless, or may in some cases lead to
  // a false positive for 1D formats, which are relatively lenient.
  // We arbitrarily say "close" is
  // "<= 1/16 of the total histogram buckets apart"
  if (secondPeak - firstPeak <= numBuckets >> 4) {
    throw IllegalArgumentException("Too little dynamic range in luminance");
  }

  // Find a valley between them that is low and closer to the white peak
  int bestValley = secondPeak - 1;
  int bestValleyScore = -1;
  for (int i = secondPeak - 1; i > firstPeak; i--) {
    int fromFirst = i - firstPeak;
    // Favor a "valley" that is not too close to either peak -- especially not
    // the black peak -- and that has a low value of course
    int score = fromFirst * fromFirst * (secondPeak - i) *
      (maxBucketCount - histogram[i]);
    if (score > bestValleyScore) {
      bestValley = i;
      bestValleyScore = score;
    }
  }

  return bestValley;
}

Ref<Binarizer> GlobalHistogramBinarizer::createBinarizer(Ref<LuminanceSource> source) {
  return Ref<Binarizer> (new GlobalHistogramBinarizer(source));
}

} // namespace zxing

<commit_msg>Slight refinement to last change - a cached row which failed should throw an exception, not return NULL.<commit_after>/*
 *  GlobalHistogramBinarizer.cpp
 *  zxing
 *
 *  Created by Ralf Kistner on 16/10/2009.
 *  Copyright 2008 ZXing authors All rights reserved.
 *  Modified by Lukasz Warchol on 02/02/2010.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include <zxing/common/GlobalHistogramBinarizer.h>

#include <zxing/common/IllegalArgumentException.h>

namespace zxing {
using namespace std;

const int LUMINANCE_BITS = 5;
const int LUMINANCE_SHIFT = 8 - LUMINANCE_BITS;
const int LUMINANCE_BUCKETS = 1 << LUMINANCE_BITS;

GlobalHistogramBinarizer::GlobalHistogramBinarizer(Ref<LuminanceSource> source) :
  Binarizer(source), cached_matrix_(NULL), cached_row_(NULL), cached_row_num_(-1) {

}

GlobalHistogramBinarizer::~GlobalHistogramBinarizer() {
}

Ref<BitArray> GlobalHistogramBinarizer::getBlackRow(int y, Ref<BitArray> row) {
  if (y == cached_row_num_) {
    if (cached_row_ != NULL) {
      return cached_row_;
    } else {
      throw IllegalArgumentException("Too little dynamic range in luminance");
    }
  }

  vector<int> histogram(LUMINANCE_BUCKETS, 0);
  LuminanceSource& source = *getLuminanceSource();
  int width = source.getWidth();
  if (row == NULL || static_cast<int>(row->getSize()) < width) {
    row = new BitArray(width);
  } else {
    row->clear();
  }

  //TODO(flyashi): cache this instead of allocating and deleting per row
  unsigned char* row_pixels = NULL;
  try {
      row_pixels = new unsigned char[width];
      getLuminanceSource()->getRow(y,row_pixels);
      for (int x = 0; x < width; x++) {
          histogram[row_pixels[x] >> LUMINANCE_SHIFT]++;
      }
      int blackPoint = estimate(histogram) << LUMINANCE_SHIFT;

      Ref<BitArray> array_ref(new BitArray(width));
      BitArray& array = *array_ref;

      int left = row_pixels[0];
      int center = row_pixels[1];
      for (int x = 1; x < width - 1; x++) {
          int right = row_pixels[x + 1];
          // A simple -1 4 -1 box filter with a weight of 2.
          int luminance = ((center << 2) - left - right) >> 1;
          if (luminance < blackPoint) {
              array.set(x);
          }
          left = center;
          center = right;
      }

      cached_row_ = array_ref;
      cached_row_num_ = y;
      delete [] row_pixels;
      return array_ref;
  } catch (IllegalArgumentException const& iae) {
      // Cache the fact that this row failed.
      cached_row_ = NULL;
      cached_row_num_ = y;
      delete [] row_pixels;
      throw iae;
  }
}

Ref<BitMatrix> GlobalHistogramBinarizer::getBlackMatrix() {
  if (cached_matrix_ != NULL) {
    return cached_matrix_;
  }

  // Faster than working with the reference
  LuminanceSource& source = *getLuminanceSource();
  int width = source.getWidth();
  int height = source.getHeight();
  vector<int> histogram(LUMINANCE_BUCKETS, 0);

  // Quickly calculates the histogram by sampling four rows from the image.
  // This proved to be more robust on the blackbox tests than sampling a
  // diagonal as we used to do.
  unsigned char* row = new unsigned char[width];
  for (int y = 1; y < 5; y++) {
    int rownum = height * y / 5;
    int right = (width << 2) / 5;
    int sdf;
    getLuminanceSource()->getRow(rownum,row);
    for (int x = width / 5; x < right; x++) {
      histogram[row[x] >> LUMINANCE_SHIFT]++;
      sdf = histogram[row[x] >> LUMINANCE_SHIFT];
    }
  }

  int blackPoint = estimate(histogram) << LUMINANCE_SHIFT;

  Ref<BitMatrix> matrix_ref(new BitMatrix(width, height));
  BitMatrix& matrix = *matrix_ref;
  for (int y = 0; y < height; y++) {
    getLuminanceSource()->getRow(y,row);
    for (int x = 0; x < width; x++) {
      if (row[x] <= blackPoint)
        matrix.set(x, y);
    }
  }

  cached_matrix_ = matrix_ref;

  delete [] row;
  return matrix_ref;
}

int GlobalHistogramBinarizer::estimate(vector<int> &histogram) {
  int numBuckets = histogram.size();
  int maxBucketCount = 0;

  // Find tallest peak in histogram
  int firstPeak = 0;
  int firstPeakSize = 0;
  for (int i = 0; i < numBuckets; i++) {
    if (histogram[i] > firstPeakSize) {
      firstPeak = i;
      firstPeakSize = histogram[i];
    }
    if (histogram[i] > maxBucketCount) {
      maxBucketCount = histogram[i];
    }
  }

  // Find second-tallest peak -- well, another peak that is tall and not
  // so close to the first one
  int secondPeak = 0;
  int secondPeakScore = 0;
  for (int i = 0; i < numBuckets; i++) {
    int distanceToBiggest = i - firstPeak;
    // Encourage more distant second peaks by multiplying by square of distance
    int score = histogram[i] * distanceToBiggest * distanceToBiggest;
    if (score > secondPeakScore) {
      secondPeak = i;
      secondPeakScore = score;
    }
  }

  // Put firstPeak first
  if (firstPeak > secondPeak) {
    int temp = firstPeak;
    firstPeak = secondPeak;
    secondPeak = temp;
  }

  // Kind of arbitrary; if the two peaks are very close, then we figure there is
  // so little dynamic range in the image, that discriminating black and white
  // is too error-prone.
  // Decoding the image/line is either pointless, or may in some cases lead to
  // a false positive for 1D formats, which are relatively lenient.
  // We arbitrarily say "close" is
  // "<= 1/16 of the total histogram buckets apart"
  if (secondPeak - firstPeak <= numBuckets >> 4) {
    throw IllegalArgumentException("Too little dynamic range in luminance");
  }

  // Find a valley between them that is low and closer to the white peak
  int bestValley = secondPeak - 1;
  int bestValleyScore = -1;
  for (int i = secondPeak - 1; i > firstPeak; i--) {
    int fromFirst = i - firstPeak;
    // Favor a "valley" that is not too close to either peak -- especially not
    // the black peak -- and that has a low value of course
    int score = fromFirst * fromFirst * (secondPeak - i) *
      (maxBucketCount - histogram[i]);
    if (score > bestValleyScore) {
      bestValley = i;
      bestValleyScore = score;
    }
  }

  return bestValley;
}

Ref<Binarizer> GlobalHistogramBinarizer::createBinarizer(Ref<LuminanceSource> source) {
  return Ref<Binarizer> (new GlobalHistogramBinarizer(source));
}

} // namespace zxing

<|endoftext|>