<commit_before>/*
 * Copyright 2007-2017 Content Management AG
 * All rights reserved.
 *
 * author: Max Kellermann <mk@cm4all.com>
 *
 * 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.
 *
 * 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
 * FOUNDATION 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 "Extract.hxx"
#include "util/StringView.hxx"
#include "util/CharUtil.hxx"

#include <assert.h>
#include <string.h>

static constexpr bool
IsValidSchemeStart(char ch) noexcept
{
	return IsLowerAlphaASCII(ch);
}

static constexpr bool
IsValidSchemeChar(char ch) noexcept
{
	return IsLowerAlphaASCII(ch) || IsDigitASCII(ch) ||
		ch == '+' || ch == '.' || ch == '-';
}

gcc_pure
static bool
IsValidScheme(StringView p) noexcept
{
	if (p.empty() || !IsValidSchemeStart(p.front()))
		return false;

	for (size_t i = 1; i < p.size; ++i)
		if (!IsValidSchemeChar(p[i]))
			return false;

	return true;
}

bool
uri_has_protocol(StringView uri) noexcept
{
	assert(!uri.IsNull());

	const char *colon = uri.Find(':');
	return colon != nullptr &&
		IsValidScheme({uri.data, colon}) &&
		colon < uri.data + uri.size - 2 &&
		colon[1] == '/' && colon[2] == '/';
}

/**
 * Return the URI part after the protocol specification (and after the
 * double slash).
 */
gcc_pure
static const char *
uri_after_protocol(const char *uri) noexcept
{
	if (uri[0] == '/' && uri[1] == '/' && uri[2] != '/')
		return uri + 2;

	const char *colon = strchr(uri, ':');
	return colon != nullptr &&
		IsValidScheme({uri, colon}) &&
		colon[1] == '/' && colon[2] == '/'
		? colon + 3
		: nullptr;
}

gcc_pure
static const char *
uri_after_protocol(StringView uri) noexcept
{
	if (uri.size > 2 && uri[0] == '/' && uri[1] == '/' && uri[2] != '/')
		return uri.data + 2;

	const char *colon = uri.Find(':');
	return colon != nullptr &&
		IsValidScheme({uri.data, colon}) &&
		colon < uri.data + uri.size - 2 &&
		colon[1] == '/' && colon[2] == '/'
		? colon + 3
		: nullptr;
}

bool
uri_has_authority(StringView uri) noexcept
{
	return uri_after_protocol(uri) != nullptr;
}

StringView
uri_host_and_port(const char *uri) noexcept
{
	assert(uri != nullptr);

	uri = uri_after_protocol(uri);
	if (uri == nullptr)
		return nullptr;

	const char *slash = strchr(uri, '/');
	if (slash == nullptr)
		return uri;

	return { uri, size_t(slash - uri) };
}

const char *
uri_path(const char *uri) noexcept
{
	assert(uri != nullptr);

	const char *ap = uri_after_protocol(uri);
	if (ap != nullptr)
		return strchr(ap, '/');

	return uri;
}

const char *
uri_query_string(const char *uri) noexcept
{
	assert(uri != nullptr);

	const char *p = strchr(uri, '?');
	if (p == nullptr || *++p == 0)
		return nullptr;

	return p;
}
<commit_msg>uri/Extract: uri_after_protocol(StringView) returns StringView<commit_after>/*
 * Copyright 2007-2017 Content Management AG
 * All rights reserved.
 *
 * author: Max Kellermann <mk@cm4all.com>
 *
 * 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.
 *
 * 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
 * FOUNDATION 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 "Extract.hxx"
#include "util/StringView.hxx"
#include "util/CharUtil.hxx"

#include <assert.h>
#include <string.h>

static constexpr bool
IsValidSchemeStart(char ch) noexcept
{
	return IsLowerAlphaASCII(ch);
}

static constexpr bool
IsValidSchemeChar(char ch) noexcept
{
	return IsLowerAlphaASCII(ch) || IsDigitASCII(ch) ||
		ch == '+' || ch == '.' || ch == '-';
}

gcc_pure
static bool
IsValidScheme(StringView p) noexcept
{
	if (p.empty() || !IsValidSchemeStart(p.front()))
		return false;

	for (size_t i = 1; i < p.size; ++i)
		if (!IsValidSchemeChar(p[i]))
			return false;

	return true;
}

bool
uri_has_protocol(StringView uri) noexcept
{
	assert(!uri.IsNull());

	const char *colon = uri.Find(':');
	return colon != nullptr &&
		IsValidScheme({uri.data, colon}) &&
		colon < uri.data + uri.size - 2 &&
		colon[1] == '/' && colon[2] == '/';
}

/**
 * Return the URI part after the protocol specification (and after the
 * double slash).
 */
gcc_pure
static const char *
uri_after_protocol(const char *uri) noexcept
{
	if (uri[0] == '/' && uri[1] == '/' && uri[2] != '/')
		return uri + 2;

	const char *colon = strchr(uri, ':');
	return colon != nullptr &&
		IsValidScheme({uri, colon}) &&
		colon[1] == '/' && colon[2] == '/'
		? colon + 3
		: nullptr;
}

gcc_pure
static StringView
uri_after_protocol(StringView uri) noexcept
{
	if (uri.size > 2 && uri[0] == '/' && uri[1] == '/' && uri[2] != '/')
		return uri.substr(2);

	const char *colon = uri.Find(':');
	return colon != nullptr &&
		IsValidScheme({uri.data, colon}) &&
		colon < uri.data + uri.size - 2 &&
		colon[1] == '/' && colon[2] == '/'
		? uri.substr(colon + 3)
		: nullptr;
}

bool
uri_has_authority(StringView uri) noexcept
{
	return uri_after_protocol(uri) != nullptr;
}

StringView
uri_host_and_port(const char *uri) noexcept
{
	assert(uri != nullptr);

	uri = uri_after_protocol(uri);
	if (uri == nullptr)
		return nullptr;

	const char *slash = strchr(uri, '/');
	if (slash == nullptr)
		return uri;

	return { uri, size_t(slash - uri) };
}

const char *
uri_path(const char *uri) noexcept
{
	assert(uri != nullptr);

	const char *ap = uri_after_protocol(uri);
	if (ap != nullptr)
		return strchr(ap, '/');

	return uri;
}

const char *
uri_query_string(const char *uri) noexcept
{
	assert(uri != nullptr);

	const char *p = strchr(uri, '?');
	if (p == nullptr || *++p == 0)
		return nullptr;

	return p;
}
<|endoftext|>


<commit_before>/******************************************************************************
 *                       ____    _    _____                                   *
 *                      / ___|  / \  |  ___|    C++                           *
 *                     | |     / _ \ | |_       Actor                         *
 *                     | |___ / ___ \|  _|      Framework                     *
 *                      \____/_/   \_|_|                                      *
 *                                                                            *
 * Copyright (C) 2011 - 2016                                                  *
 * Dominik Charousset <dominik.charousset (at) haw-hamburg.de>                *
 *                                                                            *
 * Distributed under the terms and conditions of the BSD 3-Clause License or  *
 * (at your option) under the terms and conditions of the Boost Software      *
 * License 1.0. See accompanying files LICENSE and LICENSE_ALTERNATIVE.       *
 *                                                                            *
 * If you did not receive a copy of the license files, see                    *
 * http://opensource.org/licenses/BSD-3-Clause and                            *
 * http://www.boost.org/LICENSE_1_0.txt.                                      *
 ******************************************************************************/

#ifndef CAF_STRING_ALGORITHMS_HPP
#define CAF_STRING_ALGORITHMS_HPP

#include <cmath>     // fabs
#include <string>
#include <vector>
#include <limits>
#include <sstream>
#include <algorithm>
#include <type_traits>

#include "caf/detail/type_traits.hpp"

namespace caf {

// provide boost::split compatible interface

inline std::string is_any_of(std::string arg) {
  return arg;
}

constexpr bool token_compress_on = false;

template <class Container, class Delim>
void split(Container& result, const std::string& str, const Delim& delims,
           bool keep_all = true) {
  size_t pos = 0;
  size_t prev = 0;
  while ((pos = str.find_first_of(delims, prev)) != std::string::npos) {
    if (pos > prev) {
      auto substr = str.substr(prev, pos - prev);
      if (!substr.empty() || keep_all) {
        result.push_back(std::move(substr));
      }
    }
    prev = pos + 1;
  }
  if (prev < str.size()) {
    result.push_back(str.substr(prev, std::string::npos));
  }
}

template <class Iterator>
class iterator_range {
public:
  using iterator = Iterator;

  iterator_range(iterator first, iterator last) : begin_(first), end_(last) {
    // nop
  }

  iterator begin() const {
    return begin_;
  }

  iterator end() const {
    return end_;
  }

private:
  iterator begin_;
  iterator end_;
};

template <class Container>
std::string join(const Container& c, const std::string& glue) {
  auto begin = c.begin();
  auto end = c.end();
  bool first = true;
  std::ostringstream oss;
  for ( ; begin != end; ++begin) {
    if (first)
      first = false;
    else
      oss << glue;
    oss << *begin;
  }
  return oss.str();
}

// end of recursion
inline void splice(std::string&, const std::string&) {
  // nop
}

template <class T, class... Ts>
void splice(std::string& str, const std::string& glue, T&& arg, Ts&&... xs) {
  str += glue;
  str += std::forward<T>(arg);
  splice(str, glue, std::forward<Ts>(xs)...);
}

template <ptrdiff_t WhatSize, ptrdiff_t WithSize>
void replace_all(std::string& str,
                 const char (&what)[WhatSize],
                 const char (&with)[WithSize]) {
  // end(what) - 1 points to the null-terminator
  auto next = [&](std::string::iterator pos) -> std::string::iterator {
    return std::search(pos, str.end(), std::begin(what), std::end(what) - 1);
  };
  auto i = next(std::begin(str));
  while (i != std::end(str)) {
    auto before = std::distance(std::begin(str), i);
    CAF_ASSERT(before >= 0);
    str.replace(i, i + WhatSize - 1, with);
    // i became invalidated -> use new iterator pointing
    // to the first character after the replaced text
    i = next(str.begin() + before + (WithSize - 1));
  }
}

template<size_t S>
bool starts_with(const std::string& str, const char (&prefix)[S]) {
  return str.compare(0, S, prefix);
}

template <class T>
typename std::enable_if<
  std::is_arithmetic<T>::value,
  std::string
>::type
convert_to_str(T value) {
  return std::to_string(value);
}

inline std::string convert_to_str(std::string value) {
  return value;
}

} // namespace caf

#endif // CAF_STRING_ALGORITHMS_HPP
<commit_msg>Fix caf::starts_with<commit_after>/******************************************************************************
 *                       ____    _    _____                                   *
 *                      / ___|  / \  |  ___|    C++                           *
 *                     | |     / _ \ | |_       Actor                         *
 *                     | |___ / ___ \|  _|      Framework                     *
 *                      \____/_/   \_|_|                                      *
 *                                                                            *
 * Copyright (C) 2011 - 2016                                                  *
 * Dominik Charousset <dominik.charousset (at) haw-hamburg.de>                *
 *                                                                            *
 * Distributed under the terms and conditions of the BSD 3-Clause License or  *
 * (at your option) under the terms and conditions of the Boost Software      *
 * License 1.0. See accompanying files LICENSE and LICENSE_ALTERNATIVE.       *
 *                                                                            *
 * If you did not receive a copy of the license files, see                    *
 * http://opensource.org/licenses/BSD-3-Clause and                            *
 * http://www.boost.org/LICENSE_1_0.txt.                                      *
 ******************************************************************************/

#ifndef CAF_STRING_ALGORITHMS_HPP
#define CAF_STRING_ALGORITHMS_HPP

#include <cmath>     // fabs
#include <string>
#include <vector>
#include <limits>
#include <sstream>
#include <algorithm>
#include <type_traits>

#include "caf/detail/type_traits.hpp"

namespace caf {

// provide boost::split compatible interface

inline std::string is_any_of(std::string arg) {
  return arg;
}

constexpr bool token_compress_on = false;

template <class Container, class Delim>
void split(Container& result, const std::string& str, const Delim& delims,
           bool keep_all = true) {
  size_t pos = 0;
  size_t prev = 0;
  while ((pos = str.find_first_of(delims, prev)) != std::string::npos) {
    if (pos > prev) {
      auto substr = str.substr(prev, pos - prev);
      if (!substr.empty() || keep_all) {
        result.push_back(std::move(substr));
      }
    }
    prev = pos + 1;
  }
  if (prev < str.size()) {
    result.push_back(str.substr(prev, std::string::npos));
  }
}

template <class Iterator>
class iterator_range {
public:
  using iterator = Iterator;

  iterator_range(iterator first, iterator last) : begin_(first), end_(last) {
    // nop
  }

  iterator begin() const {
    return begin_;
  }

  iterator end() const {
    return end_;
  }

private:
  iterator begin_;
  iterator end_;
};

template <class Container>
std::string join(const Container& c, const std::string& glue) {
  auto begin = c.begin();
  auto end = c.end();
  bool first = true;
  std::ostringstream oss;
  for ( ; begin != end; ++begin) {
    if (first)
      first = false;
    else
      oss << glue;
    oss << *begin;
  }
  return oss.str();
}

// end of recursion
inline void splice(std::string&, const std::string&) {
  // nop
}

template <class T, class... Ts>
void splice(std::string& str, const std::string& glue, T&& arg, Ts&&... xs) {
  str += glue;
  str += std::forward<T>(arg);
  splice(str, glue, std::forward<Ts>(xs)...);
}

template <ptrdiff_t WhatSize, ptrdiff_t WithSize>
void replace_all(std::string& str,
                 const char (&what)[WhatSize],
                 const char (&with)[WithSize]) {
  // end(what) - 1 points to the null-terminator
  auto next = [&](std::string::iterator pos) -> std::string::iterator {
    return std::search(pos, str.end(), std::begin(what), std::end(what) - 1);
  };
  auto i = next(std::begin(str));
  while (i != std::end(str)) {
    auto before = std::distance(std::begin(str), i);
    CAF_ASSERT(before >= 0);
    str.replace(i, i + WhatSize - 1, with);
    // i became invalidated -> use new iterator pointing
    // to the first character after the replaced text
    i = next(str.begin() + before + (WithSize - 1));
  }
}

template<size_t S>
bool starts_with(const std::string& str, const char (&prefix)[S]) {
  return str.compare(0, S, prefix) == 0;
}

template <class T>
typename std::enable_if<
  std::is_arithmetic<T>::value,
  std::string
>::type
convert_to_str(T value) {
  return std::to_string(value);
}

inline std::string convert_to_str(std::string value) {
  return value;
}

} // namespace caf

#endif // CAF_STRING_ALGORITHMS_HPP
<|endoftext|>


<commit_before>/*
 *  This file is part of Poedit (http://www.poedit.net)
 *
 *  Copyright (C) 1999-2008 Vaclav Slavik
 *  Copyright (C) 2005 Olivier Sannier
 *
 *  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.
 *
 *  $Id$
 *
 *  List view control
 *
 */

#include <wx/wx.h>
#include <wx/imaglist.h>
#include <wx/artprov.h>
#include <wx/dcmemory.h>
#include <wx/image.h>

#include "edlistctrl.h"
#include "digits.h"

// I don't like this global flag, but all PoeditFrame instances should share it :(
bool gs_shadedList = false;

// colours used in the list:
#define DARKEN_FACTOR      0.98

// FIXME: configurable?
static const wxColour g_ErrorColour(255, 0, 0);

static const wxColour g_TranspColour(254, 0, 253);

enum
{
    IMG_NOTHING   = 0x00,
    IMG_AUTOMATIC = 0x01,
    IMG_COMMENT   = 0x02,
    IMG_MODIFIED  = 0x04,
    IMG_BK0       =  1 << 3,
    IMG_BK1       =  2 << 3,
    IMG_BK2       =  3 << 3,
    IMG_BK3       =  4 << 3,
    IMG_BK4       =  5 << 3,
    IMG_BK5       =  6 << 3,
    IMG_BK6       =  7 << 3,
    IMG_BK7       =  8 << 3,
    IMG_BK8       =  9 << 3,
    IMG_BK9       = 10 << 3
};

BEGIN_EVENT_TABLE(PoeditListCtrl, wxListCtrl)
   EVT_SIZE(PoeditListCtrl::OnSize)
END_EVENT_TABLE()

static wxBitmap AddDigit(int digit, int x, int y, const wxBitmap& bmp)
{
    wxMemoryDC dc;
    int width = bmp.GetWidth();
    int height = bmp.GetHeight();
    wxBitmap tmpBmp(width, height);
    dc.SelectObject(tmpBmp);
    dc.SetPen(*wxTRANSPARENT_PEN);
    dc.SetBrush(wxBrush(g_TranspColour, wxSOLID));
    dc.DrawRectangle(0, 0, width, height);

    dc.DrawBitmap(bmp, 0,0,true);

    dc.SetPen(*wxBLACK_PEN);
    for(int i = 0; i < 5; i++)
    {
        for(int j = 0; j < 3; j++)
        {
            if (g_digits[digit][i][j] == 1)
                dc.DrawPoint(x+j, y+i);
        }
    }

    dc.SelectObject(wxNullBitmap);
    tmpBmp.SetMask(new wxMask(tmpBmp, g_TranspColour));
    return tmpBmp;
}

wxBitmap MergeBitmaps(const wxBitmap& bmp1, const wxBitmap& bmp2)
{
    wxMemoryDC dc;
    wxBitmap tmpBmp(bmp1.GetWidth(), bmp1.GetHeight());

    dc.SelectObject(tmpBmp);
    dc.SetPen(*wxTRANSPARENT_PEN);
    dc.SetBrush(wxBrush(g_TranspColour, wxSOLID));
    dc.DrawRectangle(0, 0, bmp1.GetWidth(), bmp1.GetHeight());
    dc.DrawBitmap(bmp1, 0, 0, true);
    dc.DrawBitmap(bmp2, 0, 0, true);
    dc.SelectObject(wxNullBitmap);

    tmpBmp.SetMask(new wxMask(tmpBmp, g_TranspColour));
    return tmpBmp;
}

wxBitmap BitmapFromList(wxImageList* list, int index)
{
    int width, height;
    list->GetSize(index, width, height);
    wxMemoryDC dc;
    wxBitmap bmp(width, height);
    dc.SelectObject(bmp);
    dc.SetPen(*wxTRANSPARENT_PEN);
    dc.SetBrush(wxBrush(g_TranspColour, wxSOLID));
    dc.DrawRectangle(0, 0, width, height);

    list->Draw(index, dc, 0, 0, wxIMAGELIST_DRAW_TRANSPARENT);

    dc.SelectObject(wxNullBitmap);
    bmp.SetMask(new wxMask(bmp, g_TranspColour));
    return bmp;
}

PoeditListCtrl::PoeditListCtrl(wxWindow *parent,
               wxWindowID id,
               const wxPoint &pos,
               const wxSize &size,
               long style,
               bool dispLines,
               const wxValidator& validator,
               const wxString &name)
     : wxListView(parent, id, pos, size, style | wxLC_VIRTUAL, validator, name)
{
    m_catalog = NULL;
    m_displayLines = dispLines;
    CreateColumns();

    int i;
    wxImageList *list = new wxImageList(16, 16);

    // IMG_NOTHING:
    list->Add(wxArtProvider::GetBitmap(_T("poedit-status-nothing")));

    // IMG_AUTOMATIC:
    list->Add(wxArtProvider::GetBitmap(_T("poedit-status-automatic")));
    // IMG_COMMENT:
    list->Add(wxArtProvider::GetBitmap(_T("poedit-status-comment")));
    // IMG_AUTOMATIC | IMG_COMMENT:
    list->Add(MergeBitmaps(wxArtProvider::GetBitmap(_T("poedit-status-automatic")),
                           wxArtProvider::GetBitmap(_T("poedit-status-comment"))));

    // IMG_MODIFIED
    list->Add(wxArtProvider::GetBitmap(_T("poedit-status-modified")));

    // IMG_MODIFIED variations:
    for (i = 1; i < IMG_MODIFIED; i++)
    {
        list->Add(MergeBitmaps(BitmapFromList(list, i),
                               wxArtProvider::GetBitmap(_T("poedit-status-modified"))));
    }

    // BK_XX variations:
    for (int bk = 0; bk < 10; bk++)
    {
        for(i = 0; i <= (IMG_AUTOMATIC|IMG_COMMENT|IMG_MODIFIED); i++)
        {
            wxBitmap bmp = BitmapFromList(list, i);
            list->Add(AddDigit(bk, 0, 0, bmp));
        }
    }

    AssignImageList(list, wxIMAGE_LIST_SMALL);

    // configure items colors & fonts:

    wxVisualAttributes visual = GetDefaultAttributes();
    wxColour shaded = visual.colBg;
    shaded.Set(int(DARKEN_FACTOR * shaded.Red()),
               int(DARKEN_FACTOR * shaded.Green()),
               int(DARKEN_FACTOR * shaded.Blue()));

    m_attrNormal[1].SetBackgroundColour(shaded);
    m_attrUntranslated[1].SetBackgroundColour(shaded);
    m_attrFuzzy[1].SetBackgroundColour(shaded);

    m_attrInvalid[0].SetTextColour(g_ErrorColour);
    m_attrInvalid[1].SetTextColour(g_ErrorColour);
    m_attrInvalid[1].SetBackgroundColour(shaded);

    wxFont fontb = visual.font;
    fontb.SetWeight(wxFONTWEIGHT_BOLD);
    m_attrUntranslated[0].SetFont(fontb);
    m_attrUntranslated[1].SetFont(fontb);

    wxFont fonti = visual.font;
    fonti.SetStyle(wxFONTSTYLE_ITALIC);
    m_attrFuzzy[0].SetFont(fonti);
    m_attrFuzzy[1].SetFont(fonti);
}

PoeditListCtrl::~PoeditListCtrl()
{
}

void PoeditListCtrl::SetDisplayLines(bool dl)
{
    m_displayLines = dl;
    CreateColumns();
}

void PoeditListCtrl::CreateColumns()
{
    DeleteAllColumns();
    InsertColumn(0, _("Original string"));
    InsertColumn(1, _("Translation"));
    if (m_displayLines)
        InsertColumn(2, _("Line"), wxLIST_FORMAT_RIGHT);
    SizeColumns();
}

void PoeditListCtrl::SizeColumns()
{
    const int LINE_COL_SIZE = m_displayLines ? 50 : 0;

    int w = GetSize().x
            - wxSystemSettings::GetMetric(wxSYS_VSCROLL_X) - 10
            - LINE_COL_SIZE;
    SetColumnWidth(0, w / 2);
    SetColumnWidth(1, w - w / 2);
    if (m_displayLines)
        SetColumnWidth(2, LINE_COL_SIZE);

    m_colWidth = (w/2) / GetCharWidth();
}

void PoeditListCtrl::CatalogChanged(Catalog* catalog)
{
    Freeze();

    // this is to prevent crashes (wxMac at least) when shortening virtual
    // listctrl when its scrolled to the bottom:
    m_catalog = NULL;
    SetItemCount(0);

    // now read the new catalog:
    m_catalog = catalog;
    ReadCatalog();

    Thaw();
}

void PoeditListCtrl::ReadCatalog()
{
    if (m_catalog == NULL)
    {
        SetItemCount(0);
        return;
    }

    // create the lookup arrays of Ids by first splitting it upon
    // four categories of items:
    // unstranslated, invalid, fuzzy and the rest
    m_itemIndexToCatalogIndexArray.clear();

    std::vector<int> untranslatedIds;
    std::vector<int> invalidIds;
    std::vector<int> fuzzyIds;
    std::vector<int> restIds;

    for (size_t i = 0; i < m_catalog->GetCount(); i++)
    {
        CatalogItem& d = (*m_catalog)[i];
        if (!d.IsTranslated())
          untranslatedIds.push_back(i);
        else if (d.GetValidity() == CatalogItem::Val_Invalid)
          invalidIds.push_back(i);
        else if (d.IsFuzzy())
          fuzzyIds.push_back(i);
        else
          restIds.push_back(i);
    }

    // Now fill the lookup array, not forgetting to set the appropriate
    // property in the catalog entry to be able to go back and forth
    // from one numbering system to the other
    m_catalogIndexToItemIndexArray.resize(m_catalog->GetCount());
    int listItemId = 0;
    for (size_t i = 0; i < untranslatedIds.size(); i++)
    {
        m_itemIndexToCatalogIndexArray.push_back(untranslatedIds[i]);
        m_catalogIndexToItemIndexArray[untranslatedIds[i]] = listItemId++;
    }
    for (size_t i = 0; i < invalidIds.size(); i++)
    {
        m_itemIndexToCatalogIndexArray.push_back(invalidIds[i]);
        m_catalogIndexToItemIndexArray[invalidIds[i]] = listItemId++;
    }
    for (size_t i = 0; i < fuzzyIds.size(); i++)
    {
        m_itemIndexToCatalogIndexArray.push_back(fuzzyIds[i]);
        m_catalogIndexToItemIndexArray[fuzzyIds[i]] = listItemId++;
    }
    for (size_t i = 0; i < restIds.size(); i++)
    {
        m_itemIndexToCatalogIndexArray.push_back(restIds[i]);
        m_catalogIndexToItemIndexArray[restIds[i]] = listItemId++;
    }

    // now that everything is prepared, we may set the item count
    SetItemCount(m_catalog->GetCount());

    // scroll to the top and refresh everything:
    if ( m_catalog->GetCount() )
    {
        Select(0);
        RefreshItems(0, m_catalog->GetCount()-1);
    }
    else
    {
        Refresh();
    }
}

wxString PoeditListCtrl::OnGetItemText(long item, long column) const
{
    if (m_catalog == NULL)
        return wxEmptyString;

    CatalogItem& d = (*m_catalog)[m_itemIndexToCatalogIndexArray[item]];
    switch (column)
    {
        case 0:
        {
            wxString orig = d.GetString();
            return orig.substr(0,GetMaxColChars());
        }
        case 1:
        {
            wxString trans = d.GetTranslation();
            return trans;
        }
        case 2:
            return wxString() << d.GetLineNumber();

        default:
            return wxEmptyString;
    }
}

wxListItemAttr *PoeditListCtrl::OnGetItemAttr(long item) const
{
    size_t idx = gs_shadedList ? size_t(item % 2) : 0;

    if (m_catalog == NULL)
        return (wxListItemAttr*)&m_attrNormal[idx];

    CatalogItem& d = (*m_catalog)[m_itemIndexToCatalogIndexArray[item]];

    if (!d.IsTranslated())
        return (wxListItemAttr*)&m_attrUntranslated[idx];
    else if (d.IsFuzzy())
        return (wxListItemAttr*)&m_attrFuzzy[idx];
    else if (d.GetValidity() == CatalogItem::Val_Invalid)
        return (wxListItemAttr*)&m_attrInvalid[idx];
    else
        return (wxListItemAttr*)&m_attrNormal[idx];
}

int PoeditListCtrl::OnGetItemImage(long item) const
{
    if (m_catalog == NULL)
        return IMG_NOTHING;

    CatalogItem& d = (*m_catalog)[m_itemIndexToCatalogIndexArray[item]];
    int index = IMG_NOTHING;

    if (d.IsAutomatic())
        index |= IMG_AUTOMATIC;
    if (d.HasComment())
        index |= IMG_COMMENT;
    if (d.IsModified())
        index |= IMG_MODIFIED;

    index |= (static_cast<int>(d.GetBookmark())+1) << 3;

    return index;
}

void PoeditListCtrl::OnSize(wxSizeEvent& event)
{
    SizeColumns();
    event.Skip();
}

long PoeditListCtrl::GetIndexInCatalog(long item) const
{
    if (item == -1)
        return -1;
    else if (item < (long)m_itemIndexToCatalogIndexArray.size())
        return m_itemIndexToCatalogIndexArray[item];
    else
        return -1;
}

int PoeditListCtrl::GetItemIndex(int catalogIndex) const
{
    if (catalogIndex == -1)
        return -1;
    else if (catalogIndex < (int)m_catalogIndexToItemIndexArray.size())
        return m_catalogIndexToItemIndexArray[catalogIndex];
    else
        return -1;
}
<commit_msg>reverted shading factor to its original value, the new one had too little contrast<commit_after>/*
 *  This file is part of Poedit (http://www.poedit.net)
 *
 *  Copyright (C) 1999-2008 Vaclav Slavik
 *  Copyright (C) 2005 Olivier Sannier
 *
 *  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.
 *
 *  $Id$
 *
 *  List view control
 *
 */

#include <wx/wx.h>
#include <wx/imaglist.h>
#include <wx/artprov.h>
#include <wx/dcmemory.h>
#include <wx/image.h>

#include "edlistctrl.h"
#include "digits.h"

// I don't like this global flag, but all PoeditFrame instances should share it :(
bool gs_shadedList = false;

// how much to darken the other color in shaded list (this value
// is what GTK+ uses in its tree view control)
#define DARKEN_FACTOR      0.95

// colours used in the list:

// FIXME: configurable?
static const wxColour g_ErrorColour(255, 0, 0);

static const wxColour g_TranspColour(254, 0, 253);

enum
{
    IMG_NOTHING   = 0x00,
    IMG_AUTOMATIC = 0x01,
    IMG_COMMENT   = 0x02,
    IMG_MODIFIED  = 0x04,
    IMG_BK0       =  1 << 3,
    IMG_BK1       =  2 << 3,
    IMG_BK2       =  3 << 3,
    IMG_BK3       =  4 << 3,
    IMG_BK4       =  5 << 3,
    IMG_BK5       =  6 << 3,
    IMG_BK6       =  7 << 3,
    IMG_BK7       =  8 << 3,
    IMG_BK8       =  9 << 3,
    IMG_BK9       = 10 << 3
};

BEGIN_EVENT_TABLE(PoeditListCtrl, wxListCtrl)
   EVT_SIZE(PoeditListCtrl::OnSize)
END_EVENT_TABLE()

static wxBitmap AddDigit(int digit, int x, int y, const wxBitmap& bmp)
{
    wxMemoryDC dc;
    int width = bmp.GetWidth();
    int height = bmp.GetHeight();
    wxBitmap tmpBmp(width, height);
    dc.SelectObject(tmpBmp);
    dc.SetPen(*wxTRANSPARENT_PEN);
    dc.SetBrush(wxBrush(g_TranspColour, wxSOLID));
    dc.DrawRectangle(0, 0, width, height);

    dc.DrawBitmap(bmp, 0,0,true);

    dc.SetPen(*wxBLACK_PEN);
    for(int i = 0; i < 5; i++)
    {
        for(int j = 0; j < 3; j++)
        {
            if (g_digits[digit][i][j] == 1)
                dc.DrawPoint(x+j, y+i);
        }
    }

    dc.SelectObject(wxNullBitmap);
    tmpBmp.SetMask(new wxMask(tmpBmp, g_TranspColour));
    return tmpBmp;
}

wxBitmap MergeBitmaps(const wxBitmap& bmp1, const wxBitmap& bmp2)
{
    wxMemoryDC dc;
    wxBitmap tmpBmp(bmp1.GetWidth(), bmp1.GetHeight());

    dc.SelectObject(tmpBmp);
    dc.SetPen(*wxTRANSPARENT_PEN);
    dc.SetBrush(wxBrush(g_TranspColour, wxSOLID));
    dc.DrawRectangle(0, 0, bmp1.GetWidth(), bmp1.GetHeight());
    dc.DrawBitmap(bmp1, 0, 0, true);
    dc.DrawBitmap(bmp2, 0, 0, true);
    dc.SelectObject(wxNullBitmap);

    tmpBmp.SetMask(new wxMask(tmpBmp, g_TranspColour));
    return tmpBmp;
}

wxBitmap BitmapFromList(wxImageList* list, int index)
{
    int width, height;
    list->GetSize(index, width, height);
    wxMemoryDC dc;
    wxBitmap bmp(width, height);
    dc.SelectObject(bmp);
    dc.SetPen(*wxTRANSPARENT_PEN);
    dc.SetBrush(wxBrush(g_TranspColour, wxSOLID));
    dc.DrawRectangle(0, 0, width, height);

    list->Draw(index, dc, 0, 0, wxIMAGELIST_DRAW_TRANSPARENT);

    dc.SelectObject(wxNullBitmap);
    bmp.SetMask(new wxMask(bmp, g_TranspColour));
    return bmp;
}

PoeditListCtrl::PoeditListCtrl(wxWindow *parent,
               wxWindowID id,
               const wxPoint &pos,
               const wxSize &size,
               long style,
               bool dispLines,
               const wxValidator& validator,
               const wxString &name)
     : wxListView(parent, id, pos, size, style | wxLC_VIRTUAL, validator, name)
{
    m_catalog = NULL;
    m_displayLines = dispLines;
    CreateColumns();

    int i;
    wxImageList *list = new wxImageList(16, 16);

    // IMG_NOTHING:
    list->Add(wxArtProvider::GetBitmap(_T("poedit-status-nothing")));

    // IMG_AUTOMATIC:
    list->Add(wxArtProvider::GetBitmap(_T("poedit-status-automatic")));
    // IMG_COMMENT:
    list->Add(wxArtProvider::GetBitmap(_T("poedit-status-comment")));
    // IMG_AUTOMATIC | IMG_COMMENT:
    list->Add(MergeBitmaps(wxArtProvider::GetBitmap(_T("poedit-status-automatic")),
                           wxArtProvider::GetBitmap(_T("poedit-status-comment"))));

    // IMG_MODIFIED
    list->Add(wxArtProvider::GetBitmap(_T("poedit-status-modified")));

    // IMG_MODIFIED variations:
    for (i = 1; i < IMG_MODIFIED; i++)
    {
        list->Add(MergeBitmaps(BitmapFromList(list, i),
                               wxArtProvider::GetBitmap(_T("poedit-status-modified"))));
    }

    // BK_XX variations:
    for (int bk = 0; bk < 10; bk++)
    {
        for(i = 0; i <= (IMG_AUTOMATIC|IMG_COMMENT|IMG_MODIFIED); i++)
        {
            wxBitmap bmp = BitmapFromList(list, i);
            list->Add(AddDigit(bk, 0, 0, bmp));
        }
    }

    AssignImageList(list, wxIMAGE_LIST_SMALL);

    // configure items colors & fonts:

    wxVisualAttributes visual = GetDefaultAttributes();
    wxColour shaded = visual.colBg;
    shaded.Set(int(DARKEN_FACTOR * shaded.Red()),
               int(DARKEN_FACTOR * shaded.Green()),
               int(DARKEN_FACTOR * shaded.Blue()));

    m_attrNormal[1].SetBackgroundColour(shaded);
    m_attrUntranslated[1].SetBackgroundColour(shaded);
    m_attrFuzzy[1].SetBackgroundColour(shaded);

    m_attrInvalid[0].SetTextColour(g_ErrorColour);
    m_attrInvalid[1].SetTextColour(g_ErrorColour);
    m_attrInvalid[1].SetBackgroundColour(shaded);

    wxFont fontb = visual.font;
    fontb.SetWeight(wxFONTWEIGHT_BOLD);
    m_attrUntranslated[0].SetFont(fontb);
    m_attrUntranslated[1].SetFont(fontb);

    wxFont fonti = visual.font;
    fonti.SetStyle(wxFONTSTYLE_ITALIC);
    m_attrFuzzy[0].SetFont(fonti);
    m_attrFuzzy[1].SetFont(fonti);
}

PoeditListCtrl::~PoeditListCtrl()
{
}

void PoeditListCtrl::SetDisplayLines(bool dl)
{
    m_displayLines = dl;
    CreateColumns();
}

void PoeditListCtrl::CreateColumns()
{
    DeleteAllColumns();
    InsertColumn(0, _("Original string"));
    InsertColumn(1, _("Translation"));
    if (m_displayLines)
        InsertColumn(2, _("Line"), wxLIST_FORMAT_RIGHT);
    SizeColumns();
}

void PoeditListCtrl::SizeColumns()
{
    const int LINE_COL_SIZE = m_displayLines ? 50 : 0;

    int w = GetSize().x
            - wxSystemSettings::GetMetric(wxSYS_VSCROLL_X) - 10
            - LINE_COL_SIZE;
    SetColumnWidth(0, w / 2);
    SetColumnWidth(1, w - w / 2);
    if (m_displayLines)
        SetColumnWidth(2, LINE_COL_SIZE);

    m_colWidth = (w/2) / GetCharWidth();
}

void PoeditListCtrl::CatalogChanged(Catalog* catalog)
{
    Freeze();

    // this is to prevent crashes (wxMac at least) when shortening virtual
    // listctrl when its scrolled to the bottom:
    m_catalog = NULL;
    SetItemCount(0);

    // now read the new catalog:
    m_catalog = catalog;
    ReadCatalog();

    Thaw();
}

void PoeditListCtrl::ReadCatalog()
{
    if (m_catalog == NULL)
    {
        SetItemCount(0);
        return;
    }

    // create the lookup arrays of Ids by first splitting it upon
    // four categories of items:
    // unstranslated, invalid, fuzzy and the rest
    m_itemIndexToCatalogIndexArray.clear();

    std::vector<int> untranslatedIds;
    std::vector<int> invalidIds;
    std::vector<int> fuzzyIds;
    std::vector<int> restIds;

    for (size_t i = 0; i < m_catalog->GetCount(); i++)
    {
        CatalogItem& d = (*m_catalog)[i];
        if (!d.IsTranslated())
          untranslatedIds.push_back(i);
        else if (d.GetValidity() == CatalogItem::Val_Invalid)
          invalidIds.push_back(i);
        else if (d.IsFuzzy())
          fuzzyIds.push_back(i);
        else
          restIds.push_back(i);
    }

    // Now fill the lookup array, not forgetting to set the appropriate
    // property in the catalog entry to be able to go back and forth
    // from one numbering system to the other
    m_catalogIndexToItemIndexArray.resize(m_catalog->GetCount());
    int listItemId = 0;
    for (size_t i = 0; i < untranslatedIds.size(); i++)
    {
        m_itemIndexToCatalogIndexArray.push_back(untranslatedIds[i]);
        m_catalogIndexToItemIndexArray[untranslatedIds[i]] = listItemId++;
    }
    for (size_t i = 0; i < invalidIds.size(); i++)
    {
        m_itemIndexToCatalogIndexArray.push_back(invalidIds[i]);
        m_catalogIndexToItemIndexArray[invalidIds[i]] = listItemId++;
    }
    for (size_t i = 0; i < fuzzyIds.size(); i++)
    {
        m_itemIndexToCatalogIndexArray.push_back(fuzzyIds[i]);
        m_catalogIndexToItemIndexArray[fuzzyIds[i]] = listItemId++;
    }
    for (size_t i = 0; i < restIds.size(); i++)
    {
        m_itemIndexToCatalogIndexArray.push_back(restIds[i]);
        m_catalogIndexToItemIndexArray[restIds[i]] = listItemId++;
    }

    // now that everything is prepared, we may set the item count
    SetItemCount(m_catalog->GetCount());

    // scroll to the top and refresh everything:
    if ( m_catalog->GetCount() )
    {
        Select(0);
        RefreshItems(0, m_catalog->GetCount()-1);
    }
    else
    {
        Refresh();
    }
}

wxString PoeditListCtrl::OnGetItemText(long item, long column) const
{
    if (m_catalog == NULL)
        return wxEmptyString;

    CatalogItem& d = (*m_catalog)[m_itemIndexToCatalogIndexArray[item]];
    switch (column)
    {
        case 0:
        {
            wxString orig = d.GetString();
            return orig.substr(0,GetMaxColChars());
        }
        case 1:
        {
            wxString trans = d.GetTranslation();
            return trans;
        }
        case 2:
            return wxString() << d.GetLineNumber();

        default:
            return wxEmptyString;
    }
}

wxListItemAttr *PoeditListCtrl::OnGetItemAttr(long item) const
{
    size_t idx = gs_shadedList ? size_t(item % 2) : 0;

    if (m_catalog == NULL)
        return (wxListItemAttr*)&m_attrNormal[idx];

    CatalogItem& d = (*m_catalog)[m_itemIndexToCatalogIndexArray[item]];

    if (!d.IsTranslated())
        return (wxListItemAttr*)&m_attrUntranslated[idx];
    else if (d.IsFuzzy())
        return (wxListItemAttr*)&m_attrFuzzy[idx];
    else if (d.GetValidity() == CatalogItem::Val_Invalid)
        return (wxListItemAttr*)&m_attrInvalid[idx];
    else
        return (wxListItemAttr*)&m_attrNormal[idx];
}

int PoeditListCtrl::OnGetItemImage(long item) const
{
    if (m_catalog == NULL)
        return IMG_NOTHING;

    CatalogItem& d = (*m_catalog)[m_itemIndexToCatalogIndexArray[item]];
    int index = IMG_NOTHING;

    if (d.IsAutomatic())
        index |= IMG_AUTOMATIC;
    if (d.HasComment())
        index |= IMG_COMMENT;
    if (d.IsModified())
        index |= IMG_MODIFIED;

    index |= (static_cast<int>(d.GetBookmark())+1) << 3;

    return index;
}

void PoeditListCtrl::OnSize(wxSizeEvent& event)
{
    SizeColumns();
    event.Skip();
}

long PoeditListCtrl::GetIndexInCatalog(long item) const
{
    if (item == -1)
        return -1;
    else if (item < (long)m_itemIndexToCatalogIndexArray.size())
        return m_itemIndexToCatalogIndexArray[item];
    else
        return -1;
}

int PoeditListCtrl::GetItemIndex(int catalogIndex) const
{
    if (catalogIndex == -1)
        return -1;
    else if (catalogIndex < (int)m_catalogIndexToItemIndexArray.size())
        return m_catalogIndexToItemIndexArray[catalogIndex];
    else
        return -1;
}
<|endoftext|>


<commit_before>/* Copyright 2014 Google Inc. All Rights Reserved.

   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.

   Example main() function for Brotli library.
*/

#include <fcntl.h>
#include <stdio.h>
#include <string>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
#include <ctime>

#include "../dec/decode.h"
#include "../enc/encode.h"
#include "../enc/streams.h"

static bool ParseQuality(const char* s, int* quality) {
  if (s[0] >= '0' && s[0] <= '9') {
    *quality = s[0] - '0';
    if (s[1] >= '0' && s[1] <= '9') {
      *quality = *quality * 10 + s[1] - '0';
      return s[2] == 0;
    }
    return s[1] == 0;
  }
  return false;
}

static void ParseArgv(int argc, char **argv,
                      char **input_path,
                      char **output_path,
                      int *force,
                      int *quality,
                      int *decompress,
                      int *repeat,
                      int *verbose) {
  *force = 0;
  *input_path = 0;
  *output_path = 0;
  *repeat = 1;
  *verbose = 0;
  {
    size_t argv0_len = strlen(argv[0]);
    *decompress =
        argv0_len >= 5 && strcmp(&argv[0][argv0_len - 5], "unbro") == 0;
  }
  for (int k = 1; k < argc; ++k) {
    if (!strcmp("--force", argv[k]) ||
        !strcmp("-f", argv[k])) {
      if (*force != 0) {
        goto error;
      }
      *force = 1;
      continue;
    } else if (!strcmp("--decompress", argv[k]) ||
               !strcmp("--uncompress", argv[k]) ||
               !strcmp("-d", argv[k])) {
      *decompress = 1;
      continue;
    } else if (!strcmp("--verbose", argv[k]) ||
               !strcmp("-v", argv[k])) {
      if (*verbose != 0) {
        goto error;
      }
      *verbose = 1;
      continue;
    }
    if (k < argc - 1) {
      if (!strcmp("--input", argv[k]) ||
          !strcmp("--in", argv[k]) ||
          !strcmp("-i", argv[k])) {
        if (*input_path != 0) {
          goto error;
        }
        *input_path = argv[k + 1];
        ++k;
        continue;
      } else if (!strcmp("--output", argv[k]) ||
                 !strcmp("--out", argv[k]) ||
                 !strcmp("-o", argv[k])) {
        if (*output_path != 0) {
          goto error;
        }
        *output_path = argv[k + 1];
        ++k;
        continue;
      } else if (!strcmp("--quality", argv[k]) ||
                 !strcmp("-q", argv[k])) {
        if (!ParseQuality(argv[k + 1], quality)) {
          goto error;
        }
        ++k;
        continue;
      } else if (!strcmp("--repeat", argv[k]) ||
                 !strcmp("-r", argv[k])) {
        if (!ParseQuality(argv[k + 1], repeat)) {
          goto error;
        }
        ++k;
        continue;
      }
    }
    goto error;
  }
  return;
error:
  fprintf(stderr,
          "Usage: %s [--force] [--quality n] [--decompress]"
          " [--input filename] [--output filename] [--repeat iters]"
          " [--verbose]\n",
          argv[0]);
  exit(1);
}

static FILE* OpenInputFile(const char* input_path) {
  if (input_path == 0) {
    setmode(STDIN_FILENO,O_BINARY);
    return stdin;
  }
  FILE* f = fopen(input_path, "rb");
  if (f == 0) {
    perror("fopen");
    exit(1);
  }
  return f;
}

static FILE *OpenOutputFile(const char *output_path, const int force) {
  if (output_path == 0) {
    setmode(STDOUT_FILENO,O_BINARY);
    return stdout;
  }
  if (!force) {
    struct stat statbuf;
    if (stat(output_path, &statbuf) == 0) {
      fprintf(stderr, "output file exists\n");
      exit(1);
    }
  }
  FILE* f = fopen(output_path, "wb");
  if (f == 0) {
    perror("fopen");
    exit(1);
  }
  return f;
}

int64_t FileSize(char *path) {
  FILE *f = fopen(path, "rb");
  if (f == NULL) {
    return -1;
  }
  fseek(f, 0L, SEEK_END);
  int64_t retval = ftell(f);
  fclose(f);
  return retval;
}

int main(int argc, char** argv) {
  char *input_path = 0;
  char *output_path = 0;
  int force = 0;
  int quality = 11;
  int decompress = 0;
  int repeat = 1;
  int verbose = 0;
  ParseArgv(argc, argv, &input_path, &output_path, &force,
            &quality, &decompress, &repeat, &verbose);
  const clock_t clock_start = clock();
  for (int i = 0; i < repeat; ++i) {
    FILE* fin = OpenInputFile(input_path);
    FILE* fout = OpenOutputFile(output_path, force);
    if (decompress) {
      BrotliInput in = BrotliFileInput(fin);
      BrotliOutput out = BrotliFileOutput(fout);
      if (!BrotliDecompress(in, out)) {
        fprintf(stderr, "corrupt input\n");
        exit(1);
      }
    } else {
      brotli::BrotliParams params;
      params.quality = quality;
      brotli::BrotliFileIn in(fin, 1 << 16);
      brotli::BrotliFileOut out(fout);
      if (!BrotliCompress(params, &in, &out)) {
        fprintf(stderr, "compression failed\n");
        unlink(output_path);
        exit(1);
      }
    }
    if (fclose(fin) != 0) {
      perror("fclose");
      exit(1);
    }
    if (fclose(fout) != 0) {
      perror("fclose");
      exit(1);
    }
  }
  if (verbose) {
    const clock_t clock_end = clock();
    double duration =
        static_cast<double>(clock_end - clock_start) / CLOCKS_PER_SEC;
    if (duration < 1e-9) {
      duration = 1e-9;
    }
    int64_t uncompressed_bytes = repeat *
        FileSize(decompress ? output_path : input_path);
    double uncompressed_bytes_in_MB = uncompressed_bytes / (1024.0 * 1024.0);
    if (decompress) {
      printf("Brotli decompression speed: ");
    } else {
      printf("Brotli compression speed: ");
    }
    printf("%g MB/s\n", uncompressed_bytes_in_MB / duration);
  }
  return 0;
}
<commit_msg>More info printed in verbose mode<commit_after>/* Copyright 2014 Google Inc. All Rights Reserved.

   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.

   Example main() function for Brotli library.
*/

#include <fcntl.h>
#include <stdio.h>
#include <string>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
#include <ctime>

#include "../dec/decode.h"
#include "../enc/encode.h"
#include "../enc/streams.h"

static bool ParseQuality(const char* s, int* quality) {
  if (s[0] >= '0' && s[0] <= '9') {
    *quality = s[0] - '0';
    if (s[1] >= '0' && s[1] <= '9') {
      *quality = *quality * 10 + s[1] - '0';
      return s[2] == 0;
    }
    return s[1] == 0;
  }
  return false;
}

static void ParseArgv(int argc, char **argv,
                      char **input_path,
                      char **output_path,
                      int *force,
                      int *quality,
                      int *decompress,
                      int *repeat,
                      int *verbose) {
  *force = 0;
  *input_path = 0;
  *output_path = 0;
  *repeat = 1;
  *verbose = 0;
  {
    size_t argv0_len = strlen(argv[0]);
    *decompress =
        argv0_len >= 5 && strcmp(&argv[0][argv0_len - 5], "unbro") == 0;
  }
  for (int k = 1; k < argc; ++k) {
    if (!strcmp("--force", argv[k]) ||
        !strcmp("-f", argv[k])) {
      if (*force != 0) {
        goto error;
      }
      *force = 1;
      continue;
    } else if (!strcmp("--decompress", argv[k]) ||
               !strcmp("--uncompress", argv[k]) ||
               !strcmp("-d", argv[k])) {
      *decompress = 1;
      continue;
    } else if (!strcmp("--verbose", argv[k]) ||
               !strcmp("-v", argv[k])) {
      if (*verbose != 0) {
        goto error;
      }
      *verbose = 1;
      continue;
    }
    if (k < argc - 1) {
      if (!strcmp("--input", argv[k]) ||
          !strcmp("--in", argv[k]) ||
          !strcmp("-i", argv[k])) {
        if (*input_path != 0) {
          goto error;
        }
        *input_path = argv[k + 1];
        ++k;
        continue;
      } else if (!strcmp("--output", argv[k]) ||
                 !strcmp("--out", argv[k]) ||
                 !strcmp("-o", argv[k])) {
        if (*output_path != 0) {
          goto error;
        }
        *output_path = argv[k + 1];
        ++k;
        continue;
      } else if (!strcmp("--quality", argv[k]) ||
                 !strcmp("-q", argv[k])) {
        if (!ParseQuality(argv[k + 1], quality)) {
          goto error;
        }
        ++k;
        continue;
      } else if (!strcmp("--repeat", argv[k]) ||
                 !strcmp("-r", argv[k])) {
        if (!ParseQuality(argv[k + 1], repeat)) {
          goto error;
        }
        ++k;
        continue;
      }
    }
    goto error;
  }
  return;
error:
  fprintf(stderr,
          "Usage: %s [--force] [--quality n] [--decompress]"
          " [--input filename] [--output filename] [--repeat iters]"
          " [--verbose]\n",
          argv[0]);
  exit(1);
}

static FILE* OpenInputFile(const char* input_path) {
  if (input_path == 0) {
    setmode(STDIN_FILENO,O_BINARY);
    return stdin;
  }
  FILE* f = fopen(input_path, "rb");
  if (f == 0) {
    perror("fopen");
    exit(1);
  }
  return f;
}

static FILE *OpenOutputFile(const char *output_path, const int force) {
  if (output_path == 0) {
    setmode(STDOUT_FILENO,O_BINARY);
    return stdout;
  }
  if (!force) {
    struct stat statbuf;
    if (stat(output_path, &statbuf) == 0) {
      fprintf(stderr, "output file exists\n");
      exit(1);
    }
  }
  FILE* f = fopen(output_path, "wb");
  if (f == 0) {
    perror("fopen");
    exit(1);
  }
  return f;
}

int64_t FileSize(char *path) {
  FILE *f = fopen(path, "rb");
  if (f == NULL) {
    return -1;
  }
  fseek(f, 0L, SEEK_END);
  int64_t retval = ftell(f);
  fclose(f);
  return retval;
}

int main(int argc, char** argv) {
  char *input_path = 0;
  char *output_path = 0;
  int force = 0;
  int quality = 11;
  int decompress = 0;
  int repeat = 1;
  int verbose = 0;
  ParseArgv(argc, argv, &input_path, &output_path, &force,
            &quality, &decompress, &repeat, &verbose);
  const clock_t clock_start = clock();
  for (int i = 0; i < repeat; ++i) {
    FILE* fin = OpenInputFile(input_path);
    FILE* fout = OpenOutputFile(output_path, force);
    if (decompress) {
      BrotliInput in = BrotliFileInput(fin);
      BrotliOutput out = BrotliFileOutput(fout);
      if (!BrotliDecompress(in, out)) {
        fprintf(stderr, "corrupt input\n");
        exit(1);
      }
    } else {
      brotli::BrotliParams params;
      params.quality = quality;
      brotli::BrotliFileIn in(fin, 1 << 16);
      brotli::BrotliFileOut out(fout);
      if (!BrotliCompress(params, &in, &out)) {
        fprintf(stderr, "compression failed\n");
        unlink(output_path);
        exit(1);
      }
    }
    if (fclose(fin) != 0) {
      perror("fclose");
      exit(1);
    }
    if (fclose(fout) != 0) {
      perror("fclose");
      exit(1);
    }
  }
  if (verbose) {
    const clock_t clock_end = clock();
    double duration =
        static_cast<double>(clock_end - clock_start) / CLOCKS_PER_SEC;
    if (duration < 1e-9) {
      duration = 1e-9;
    }
    double insize  = static_cast<double> (FileSize(input_path));
    double outsize = static_cast<double> (FileSize(output_path));
    double uncompressed_bytes = repeat * (decompress ? outsize : insize);

    double uncompressed_bytes_in_MB = uncompressed_bytes / (1024.0 * 1024.0);
    if (decompress) {
      printf("%.0lf -> %.0lf: %.3lf%%", outsize, insize, insize*100.0/outsize);
    } else {
      printf("%.0lf -> %.0lf: %.3lf%%", insize, outsize, outsize*100.0/insize);
    }
    printf(",  %.3lf sec,  %.3lf MiB/s\n", duration, uncompressed_bytes_in_MB / duration);
  }
  return 0;
}
<|endoftext|>


<commit_before>/*
Copyright (c) 2013 Microsoft Corporation. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.

Author: Leonardo de Moura
*/
#include <utility>
#include <pthread.h>
#include <vector>
#include <iostream>
#if defined(LEAN_WINDOWS)
#include <windows.h>
#endif
#include "util/thread.h"
#include "util/exception.h"

#ifndef LEAN_DEFAULT_THREAD_STACK_SIZE
#define LEAN_DEFAULT_THREAD_STACK_SIZE 8*1024*1024 // 8Mb
#endif

namespace lean {
#if defined(LEAN_MULTI_THREAD)
size_t lthread::m_thread_stack_size = LEAN_DEFAULT_THREAD_STACK_SIZE;

void lthread::set_thread_stack_size(size_t sz) {
    m_thread_stack_size = sz + LEAN_STACK_BUFFER_SPACE;
}

size_t lthread::get_thread_stack_size() {
    return m_thread_stack_size;
}

#if defined(LEAN_WINDOWS)
/* Windows version */
struct lthread::imp {
    std::function<void(void)> m_proc;
    HANDLE                    m_thread;

    static DWORD WINAPI _main(void * p) {
        (*reinterpret_cast<std::function<void(void)>*>(p))();
        return 0;
    }

    imp(std::function<void(void)> const & p):
        m_proc(p) {
        m_thread = CreateThread(nullptr, m_thread_stack_size,
                                _main, &m_proc, 0, nullptr);
        if (m_thread == NULL) {
            throw exception("failed to create thread");
        }
    }

    void join() {
        if (WaitForSingleObject(m_thread, INFINITE) == WAIT_FAILED) {
            throw exception("failed to join thread");
        }
    }
};
#else
/* OSX/Linux version based on pthreads */
struct lthread::imp {
    std::function<void(void)> m_proc;
    pthread_attr_t            m_attr;
    pthread_t                 m_thread;

    static void * _main(void * p) {
        (*reinterpret_cast<std::function<void(void)>*>(p))();
        return nullptr;
    }

    imp(std::function<void(void)> const & p):
        m_proc(p) {
        pthread_attr_init(&m_attr);
        if (pthread_attr_setstacksize(&m_attr, m_thread_stack_size)) {
            throw exception("failed to set thread stack size");
        }
        if (pthread_create(&m_thread, &m_attr, _main, &m_proc)) {
            throw exception("failed to create thread");
        }
    }
    ~imp() {
        pthread_attr_destroy(&m_attr);
    }

    void join() {
        if (pthread_join(m_thread, nullptr)) {
            throw exception("failed to join thread");
        }
    }
};
#endif
lthread::lthread(std::function<void(void)> const & p):m_imp(new imp(p)) {}

lthread::~lthread() {}

void lthread::join() { m_imp->join(); }
#endif

void initialize_thread() {}
void finalize_thread() {}

LEAN_THREAD_VALUE(bool, g_finalizing, false);

bool in_thread_finalization() {
    return g_finalizing;
}

typedef std::vector<std::pair<thread_finalizer, void*>> thread_finalizers;

void run_thread_finalizers_core(thread_finalizers & fns) {
    g_finalizing = true;
    unsigned i = fns.size();
    while (i > 0) {
        --i;
        auto fn = fns[i].first;
        fn(fns[i].second);
    }
    fns.clear();
}

// We have two different implementations of the following procedures.
//
//   void register_thread_finalizer(thread_finalizer fn, void * p);
//   void register_post_thread_finalizer(thread_finalizer fn, void * p);
//   void run_thread_finalizers();
//
// The implementation is selected by using the LEAN_AUTO_THREAD_FINALIZATION compilation directive.
// We can remove the implementation based on pthreads after the new thread_local C++11 keyword is properly
// implemented in all platforms.
// In the meantime, when LEAN_AUTO_THREAD_FINALIZATION is defined/set, we use a thread finalization
// procedure based on the pthread API.
// Remark: we only need this feature when Lean is being used as a library.
// Example: the C API is being used from Haskell, and the execution threads
// are being created by Haskell.
// Remark: for the threads created by Lean, we explicitly create the thread finalizers.
// The idea is to avoid memory leaks even when LEAN_AUTO_THREAD_FINALIZATION is not used.

#if defined(LEAN_AUTO_THREAD_FINALIZATION)
// pthread based implementation

typedef std::pair<thread_finalizers, thread_finalizers> thread_finalizers_pair;

class thread_finalizers_manager {
    pthread_key_t g_key;
public:
    thread_finalizers_manager() {
        pthread_key_create(&g_key, finalize_thread);
        init_thread(); // initialize main thread
    }

    ~thread_finalizers_manager() {
        finalize_thread(get_pair()); // finalize main thread
        pthread_key_delete(g_key);
    }

    thread_finalizers_pair * get_pair() {
        return reinterpret_cast<thread_finalizers_pair*>(pthread_getspecific(g_key));
    }

    void init_thread() {
        if (get_pair() == nullptr) {
            thread_finalizers_pair * p = new thread_finalizers_pair();
            pthread_setspecific(g_key, p);
        }
    }

    thread_finalizers & get_thread_finalizers() {
        init_thread();
        return get_pair()->first;
    }

    thread_finalizers & get_post_thread_finalizers() {
        init_thread();
        return get_pair()->second;
    }

    static void finalize_thread(void * d) {
        if (d) {
            thread_finalizers_pair * p = reinterpret_cast<thread_finalizers_pair*>(d);
            run_thread_finalizers_core(p->first);
            run_thread_finalizers_core(p->second);
            delete p;
        }
    }
};

static thread_finalizers_manager * g_aux = nullptr;

thread_finalizers_manager & get_manager() {
    if (!g_aux)
        g_aux = new thread_finalizers_manager();
    return *g_aux;
}

void delete_thread_finalizer_manager() {
    delete g_aux;
}

void register_thread_finalizer(thread_finalizer fn, void * p) {
    get_manager().get_thread_finalizers().emplace_back(fn, p);
}

void register_post_thread_finalizer(thread_finalizer fn, void * p) {
    get_manager().get_post_thread_finalizers().emplace_back(fn, p);
}

void run_thread_finalizers() {
}

void run_post_thread_finalizers() {
}
#else
// reference implementation
LEAN_THREAD_PTR(thread_finalizers, g_finalizers);
LEAN_THREAD_PTR(thread_finalizers, g_post_finalizers);

void delete_thread_finalizer_manager() {}

void register_thread_finalizer(thread_finalizer fn, void * p) {
    if (!g_finalizers)
        g_finalizers = new thread_finalizers();
    g_finalizers->emplace_back(fn, p);
}

void register_post_thread_finalizer(thread_finalizer fn, void * p) {
    if (!g_post_finalizers)
        g_post_finalizers = new thread_finalizers();
    g_post_finalizers->emplace_back(fn, p);
}

void run_thread_finalizers(thread_finalizers * fns) {
    if (fns) {
        run_thread_finalizers_core(*fns);
        delete fns;
    }
}

void run_thread_finalizers() {
    run_thread_finalizers(g_finalizers);
    g_finalizers      = nullptr;
}

void run_post_thread_finalizers() {
    run_thread_finalizers(g_post_finalizers);
    g_post_finalizers = nullptr;
}
#endif
}
<commit_msg>fix(util/thread): do not initialize thread_finalizers_manager in multiple threads<commit_after>/*
Copyright (c) 2013 Microsoft Corporation. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.

Author: Leonardo de Moura
*/
#include <utility>
#include <pthread.h>
#include <vector>
#include <iostream>
#if defined(LEAN_WINDOWS)
#include <windows.h>
#endif
#include "util/thread.h"
#include "util/exception.h"

#ifndef LEAN_DEFAULT_THREAD_STACK_SIZE
#define LEAN_DEFAULT_THREAD_STACK_SIZE 8*1024*1024 // 8Mb
#endif

namespace lean {
#if defined(LEAN_MULTI_THREAD)
size_t lthread::m_thread_stack_size = LEAN_DEFAULT_THREAD_STACK_SIZE;

void lthread::set_thread_stack_size(size_t sz) {
    m_thread_stack_size = sz + LEAN_STACK_BUFFER_SPACE;
}

size_t lthread::get_thread_stack_size() {
    return m_thread_stack_size;
}

#if defined(LEAN_WINDOWS)
/* Windows version */
struct lthread::imp {
    std::function<void(void)> m_proc;
    HANDLE                    m_thread;

    static DWORD WINAPI _main(void * p) {
        (*reinterpret_cast<std::function<void(void)>*>(p))();
        return 0;
    }

    imp(std::function<void(void)> const & p):
        m_proc(p) {
        m_thread = CreateThread(nullptr, m_thread_stack_size,
                                _main, &m_proc, 0, nullptr);
        if (m_thread == NULL) {
            throw exception("failed to create thread");
        }
    }

    void join() {
        if (WaitForSingleObject(m_thread, INFINITE) == WAIT_FAILED) {
            throw exception("failed to join thread");
        }
    }
};
#else
/* OSX/Linux version based on pthreads */
struct lthread::imp {
    std::function<void(void)> m_proc;
    pthread_attr_t            m_attr;
    pthread_t                 m_thread;

    static void * _main(void * p) {
        (*reinterpret_cast<std::function<void(void)>*>(p))();
        return nullptr;
    }

    imp(std::function<void(void)> const & p):
        m_proc(p) {
        pthread_attr_init(&m_attr);
        if (pthread_attr_setstacksize(&m_attr, m_thread_stack_size)) {
            throw exception("failed to set thread stack size");
        }
        if (pthread_create(&m_thread, &m_attr, _main, &m_proc)) {
            throw exception("failed to create thread");
        }
    }
    ~imp() {
        pthread_attr_destroy(&m_attr);
    }

    void join() {
        if (pthread_join(m_thread, nullptr)) {
            throw exception("failed to join thread");
        }
    }
};
#endif
lthread::lthread(std::function<void(void)> const & p):m_imp(new imp(p)) {}

lthread::~lthread() {}

void lthread::join() { m_imp->join(); }
#endif

LEAN_THREAD_VALUE(bool, g_finalizing, false);

bool in_thread_finalization() {
    return g_finalizing;
}

typedef std::vector<std::pair<thread_finalizer, void*>> thread_finalizers;

void run_thread_finalizers_core(thread_finalizers & fns) {
    g_finalizing = true;
    unsigned i = fns.size();
    while (i > 0) {
        --i;
        auto fn = fns[i].first;
        fn(fns[i].second);
    }
    fns.clear();
}

// We have two different implementations of the following procedures.
//
//   void register_thread_finalizer(thread_finalizer fn, void * p);
//   void register_post_thread_finalizer(thread_finalizer fn, void * p);
//   void run_thread_finalizers();
//
// The implementation is selected by using the LEAN_AUTO_THREAD_FINALIZATION compilation directive.
// We can remove the implementation based on pthreads after the new thread_local C++11 keyword is properly
// implemented in all platforms.
// In the meantime, when LEAN_AUTO_THREAD_FINALIZATION is defined/set, we use a thread finalization
// procedure based on the pthread API.
// Remark: we only need this feature when Lean is being used as a library.
// Example: the C API is being used from Haskell, and the execution threads
// are being created by Haskell.
// Remark: for the threads created by Lean, we explicitly create the thread finalizers.
// The idea is to avoid memory leaks even when LEAN_AUTO_THREAD_FINALIZATION is not used.

#if defined(LEAN_AUTO_THREAD_FINALIZATION)
// pthread based implementation

typedef std::pair<thread_finalizers, thread_finalizers> thread_finalizers_pair;

class thread_finalizers_manager {
    pthread_key_t g_key;
public:
    thread_finalizers_manager() {
        pthread_key_create(&g_key, finalize_thread);
        init_thread(); // initialize main thread
    }

    ~thread_finalizers_manager() {
        finalize_thread(get_pair()); // finalize main thread
        pthread_key_delete(g_key);
    }

    thread_finalizers_pair * get_pair() {
        return reinterpret_cast<thread_finalizers_pair*>(pthread_getspecific(g_key));
    }

    void init_thread() {
        if (get_pair() == nullptr) {
            thread_finalizers_pair * p = new thread_finalizers_pair();
            pthread_setspecific(g_key, p);
        }
    }

    thread_finalizers & get_thread_finalizers() {
        init_thread();
        return get_pair()->first;
    }

    thread_finalizers & get_post_thread_finalizers() {
        init_thread();
        return get_pair()->second;
    }

    static void finalize_thread(void * d) {
        if (d) {
            thread_finalizers_pair * p = reinterpret_cast<thread_finalizers_pair*>(d);
            run_thread_finalizers_core(p->first);
            run_thread_finalizers_core(p->second);
            delete p;
        }
    }
};

static thread_finalizers_manager * g_thread_finalizers_mgr = nullptr;

void delete_thread_finalizer_manager() {
    delete g_thread_finalizers_mgr;
    g_thread_finalizers_mgr = nullptr;
}

void register_thread_finalizer(thread_finalizer fn, void * p) {
    g_thread_finalizers_mgr->get_thread_finalizers().emplace_back(fn, p);
}

void register_post_thread_finalizer(thread_finalizer fn, void * p) {
    g_thread_finalizers_mgr->get_post_thread_finalizers().emplace_back(fn, p);
}

void run_thread_finalizers() {
}

void run_post_thread_finalizers() {
}

void initialize_thread() {
    g_thread_finalizers_mgr = new thread_finalizers_manager;
}
void finalize_thread() {}
#else
// reference implementation
LEAN_THREAD_PTR(thread_finalizers, g_finalizers);
LEAN_THREAD_PTR(thread_finalizers, g_post_finalizers);

void delete_thread_finalizer_manager() {}

void register_thread_finalizer(thread_finalizer fn, void * p) {
    if (!g_finalizers)
        g_finalizers = new thread_finalizers();
    g_finalizers->emplace_back(fn, p);
}

void register_post_thread_finalizer(thread_finalizer fn, void * p) {
    if (!g_post_finalizers)
        g_post_finalizers = new thread_finalizers();
    g_post_finalizers->emplace_back(fn, p);
}

void run_thread_finalizers(thread_finalizers * fns) {
    if (fns) {
        run_thread_finalizers_core(*fns);
        delete fns;
    }
}

void run_thread_finalizers() {
    run_thread_finalizers(g_finalizers);
    g_finalizers      = nullptr;
}

void run_post_thread_finalizers() {
    run_thread_finalizers(g_post_finalizers);
    g_post_finalizers = nullptr;
}

void initialize_thread() {}
void finalize_thread() {}
#endif
}
<|endoftext|>


<commit_before>/* +---------------------------------------------------------------------------+
   |                     Mobile Robot Programming Toolkit (MRPT)               |
   |                          http://www.mrpt.org/                             |
   |                                                                           |
   | Copyright (c) 2005-2014, Individual contributors, see AUTHORS file        |
   | See: http://www.mrpt.org/Authors - All rights reserved.                   |
   | Released under BSD License. See details in http://www.mrpt.org/License    |
   +---------------------------------------------------------------------------+ */

#include "hwdrivers-precomp.h"   // Precompiled headers

#include <mrpt/hwdrivers/CRoboPeakLidar.h>
#include <mrpt/hwdrivers/CSerialPort.h>
#include <mrpt/utils/CClientTCPSocket.h>
#include <mrpt/system/os.h>

IMPLEMENTS_GENERIC_SENSOR(CRoboPeakLidar,mrpt::hwdrivers)

#if MRPT_HAS_ROBOPEAK_LIDAR
#	include "rplidar.h" // RPLidar API
using namespace rp::standalone::rplidar;
#	define RPLIDAR_DRV   static_cast<RPlidarDriver*>(m_rplidar_drv)
#endif

using namespace mrpt::utils;
using namespace mrpt::slam;
using namespace mrpt::hwdrivers;
using namespace mrpt::system;
using namespace mrpt::opengl;
using namespace std;

/*-------------------------------------------------------------
						Constructor
-------------------------------------------------------------*/
CRoboPeakLidar::CRoboPeakLidar() :
	m_com_port(""),
	m_com_port_baudrate(115200),
	m_rplidar_drv(NULL)
{
	m_sensorLabel = "RPLidar";
}

/*-------------------------------------------------------------
					~CRoboPeakLidar
-------------------------------------------------------------*/
CRoboPeakLidar::~CRoboPeakLidar()
{
	turnOff();
	disconnect();
}

void CRoboPeakLidar::disconnect()
{
#if MRPT_HAS_ROBOPEAK_LIDAR
	RPlidarDriver::DisposeDriver(RPLIDAR_DRV);
	m_rplidar_drv=NULL;
#endif
}

/*-------------------------------------------------------------
						doProcessSimple
-------------------------------------------------------------*/
void  CRoboPeakLidar::doProcessSimple(
	bool							&outThereIsObservation,
	mrpt::slam::CObservation2DRangeScan	&outObservation,
	bool							&hardwareError )
{
#if MRPT_HAS_ROBOPEAK_LIDAR
	outThereIsObservation	= false;
	hardwareError			= false;

	// Bound?
	if (!checkCOMMs())
	{
		hardwareError = true;
		return;
	}

	rplidar_response_measurement_node_t nodes[360*2];
    size_t   count = sizeof(nodes)/sizeof(nodes[0]);

	const float angle_min = DEG2RAD(0.0f);
    const float angle_max = DEG2RAD(359.0f);

	// Scan:
	const mrpt::system::TTimeStamp tim_scan_start = mrpt::system::now();
	u_result op_result = RPLIDAR_DRV->grabScanData(nodes, count);
	//const mrpt::system::TTimeStamp tim_scan_end = mrpt::system::now();
	//const double scan_duration = mrpt::system::timeDifference(tim_scan_start,tim_scan_end);

	// Fill in scan data:
    if (op_result == RESULT_OK)
	{
        op_result = RPLIDAR_DRV->ascendScanData(nodes, count);
        if (op_result == RESULT_OK)
		{
            const size_t angle_compensate_nodes_count = 360;
            const size_t angle_compensate_multiple = 1;
            int angle_compensate_offset = 0;
            rplidar_response_measurement_node_t angle_compensate_nodes[angle_compensate_nodes_count];
            memset(angle_compensate_nodes, 0, angle_compensate_nodes_count*sizeof(rplidar_response_measurement_node_t));

			outObservation.scan.assign(count, 0);
			outObservation.validRange.resize(count, 0);

			for(size_t i=0 ; i < count; i++ )
			{
                if (nodes[i].distance_q2 != 0)
				{
                    float angle = (float)((nodes[i].angle_q6_checkbit >> RPLIDAR_RESP_MEASUREMENT_ANGLE_SHIFT)/64.0f);
                    int angle_value = (int)(angle * angle_compensate_multiple);
                    if ((angle_value - angle_compensate_offset) < 0) angle_compensate_offset = angle_value;
                    for (size_t j = 0; j < angle_compensate_multiple; j++)
					{
                        angle_compensate_nodes[angle_value-angle_compensate_offset+j] = nodes[i];
                    }
                }
			}

			for(size_t i=0 ; i < count; i++ )
			{
				const float read_value = (float) angle_compensate_nodes[i].distance_q2/4.0f/1000;
				outObservation.scan[i] = read_value;
				outObservation.validRange[i] = (read_value>0);
			}
        }
		else if (op_result == RESULT_OPERATION_FAIL)
		{
            // All the data is invalid, just publish them
			outObservation.scan.assign(count, 0);
			outObservation.validRange.resize(count, 0);
        }

		// Fill common parts of the obs:
		outObservation.timestamp = tim_scan_start;
		outObservation.rightToLeft = false;
		outObservation.aperture = 2.0*M_PI;
		outObservation.maxRange	= 6.0;
		outObservation.stdError = 0.010f;
		outObservation.sensorPose = m_sensorPose;
		outObservation.sensorLabel = m_sensorLabel;

		// Do filter:
		C2DRangeFinderAbstract::filterByExclusionAreas( outObservation );
		C2DRangeFinderAbstract::filterByExclusionAngles( outObservation );
		// Do show preview:
		C2DRangeFinderAbstract::processPreview(outObservation);

		outThereIsObservation = true;
    }
	else
	{
		if (op_result==RESULT_OPERATION_TIMEOUT || op_result==RESULT_OPERATION_FAIL)
		{
			// Error? Retry connection
			this->disconnect();
		}
	}

#endif
}

/*-------------------------------------------------------------
						loadConfig_sensorSpecific
-------------------------------------------------------------*/
void  CRoboPeakLidar::loadConfig_sensorSpecific(
	const mrpt::utils::CConfigFileBase &configSource,
	const std::string	  &iniSection )
{
	m_sensorPose.setFromValues(
		configSource.read_float(iniSection,"pose_x",0),
		configSource.read_float(iniSection,"pose_y",0),
		configSource.read_float(iniSection,"pose_z",0),
		DEG2RAD( configSource.read_float(iniSection,"pose_yaw",0) ),
		DEG2RAD( configSource.read_float(iniSection,"pose_pitch",0) ),
		DEG2RAD( configSource.read_float(iniSection,"pose_roll",0) )
		);

#ifdef MRPT_OS_WINDOWS
	m_com_port = configSource.read_string(iniSection, "COM_port_WIN", m_com_port, true );
#else
	m_com_port = configSource.read_string(iniSection, "COM_port_LIN", m_com_port, true );
#endif

	// Parent options:
	this->loadCommonParams(configSource,iniSection);
}

/*-------------------------------------------------------------
						turnOn
-------------------------------------------------------------*/
bool  CRoboPeakLidar::turnOn()
{
	return checkCOMMs();
}

/*-------------------------------------------------------------
						turnOff
-------------------------------------------------------------*/
bool  CRoboPeakLidar::turnOff()
{
#if MRPT_HAS_ROBOPEAK_LIDAR
	if (RPLIDAR_DRV) RPLIDAR_DRV->stop();
	return true;
#else
	THROW_EXCEPTION("MRPT has been compiled without RPLidar support!")
#endif
}

/** Returns true if the device is connected & operative */
bool CRoboPeakLidar::getDeviceHealth() const
{
#if MRPT_HAS_ROBOPEAK_LIDAR
	if (!RPLIDAR_DRV) return false;

	rplidar_response_device_health_t healthinfo;

	u_result op_result = RPLIDAR_DRV->getHealth(healthinfo);
	if (IS_OK(op_result))
	{
		printf("[CRoboPeakLidar] RPLidar health status : %d\n", healthinfo.status);
		if (healthinfo.status != RPLIDAR_STATUS_OK)
		{
			fprintf(stderr, "[CRoboPeakLidar] Error, rplidar internal error detected. Please reboot the device to retry.\n");
			return false;
		}
	}
	else
	{
		fprintf(stderr, "[CRoboPeakLidar] Error, cannot retrieve rplidar health code: %x\n", op_result);
		return false;
	}

	return true;
#else
	THROW_EXCEPTION("MRPT has been compiled without RPLidar support!")
#endif
}

/*-------------------------------------------------------------
						checkCOMMs
-------------------------------------------------------------*/
bool  CRoboPeakLidar::checkCOMMs()
{
	MRPT_START
#if MRPT_HAS_ROBOPEAK_LIDAR
	if (RPLIDAR_DRV)
		return true;

	// create the driver instance
	m_rplidar_drv = RPlidarDriver::CreateDriver(RPlidarDriver::DRIVER_TYPE_SERIALPORT);
	ASSERTMSG_(m_rplidar_drv, "Create Driver failed.")

	// Is it COMX, X>4? ->  "\\.\COMX"
	if (m_com_port.size()>=3)
	{
		if ( tolower( m_com_port[0]) =='c' && tolower( m_com_port[1]) =='o' && tolower( m_com_port[2]) =='m' )
		{
			// Need to add "\\.\"?
			if (m_com_port.size()>4 || m_com_port[3]>'4')
				m_com_port = std::string("\\\\.\\") + m_com_port;
		}
	}

	// make connection...
	if (IS_FAIL(RPLIDAR_DRV->connect( m_com_port.c_str(), (_u32)m_com_port_baudrate)))
	{
		fprintf(stderr, "[CRoboPeakLidar] Error, cannot bind to the specified serial port %s\n",  m_com_port.c_str() );
		return false;
	}

	rplidar_response_device_info_t devinfo;
	if (IS_FAIL(RPLIDAR_DRV->getDeviceInfo(devinfo) ))
	{
		return false;
	}

	if (m_verbose)
	{
		printf("[CRoboPeakLidar] Connection established:\n"
			"Firmware version: %u\n"
			"Hardware version: %u\n"
			"Model: %u\n"
			"Serial: ",
			(unsigned int)devinfo.firmware_version,
			(unsigned int)devinfo.hardware_version,
			(unsigned int)devinfo.model);

		for (int i=0;i<16;i++)
			printf("%02X",devinfo.serialnum[i]);
		printf("\n");
	}

	// check health:
	if (!getDeviceHealth())
		return false;

	// start scan...
	u_result res = RPLIDAR_DRV->startScan();
	if (IS_FAIL( res ))
	{
		fprintf(stderr, "[CRoboPeakLidar] Error starting scanning mode: %x\n", res);
		return false;
	}

	return true;
#else
	THROW_EXCEPTION("MRPT has been compiled without RPLidar support!")
#endif
	MRPT_END
}

/*-------------------------------------------------------------
						initialize
-------------------------------------------------------------*/
void CRoboPeakLidar::initialize()
{
	if (!checkCOMMs()) return;

	if (!turnOn())
	{
		cerr << "[CRoboPeakLidar::initialize] Error initializing RPLIDAR scanner" << endl;
		return;
	}

}

void CRoboPeakLidar::setSerialPort(const std::string &port_name)
{
	if (m_rplidar_drv)
		THROW_EXCEPTION("Can't change serial port while connected!")

	m_com_port = port_name;
}

<commit_msg>fix warnings (and indent)<commit_after>/* +---------------------------------------------------------------------------+
   |                     Mobile Robot Programming Toolkit (MRPT)               |
   |                          http://www.mrpt.org/                             |
   |                                                                           |
   | Copyright (c) 2005-2014, Individual contributors, see AUTHORS file        |
   | See: http://www.mrpt.org/Authors - All rights reserved.                   |
   | Released under BSD License. See details in http://www.mrpt.org/License    |
   +---------------------------------------------------------------------------+ */

#include "hwdrivers-precomp.h"   // Precompiled headers

#include <mrpt/hwdrivers/CRoboPeakLidar.h>
#include <mrpt/hwdrivers/CSerialPort.h>
#include <mrpt/utils/CClientTCPSocket.h>
#include <mrpt/system/os.h>

IMPLEMENTS_GENERIC_SENSOR(CRoboPeakLidar,mrpt::hwdrivers)

#if MRPT_HAS_ROBOPEAK_LIDAR
#	include "rplidar.h" // RPLidar API
using namespace rp::standalone::rplidar;
#	define RPLIDAR_DRV   static_cast<RPlidarDriver*>(m_rplidar_drv)
#endif

using namespace mrpt::utils;
using namespace mrpt::slam;
using namespace mrpt::hwdrivers;
using namespace mrpt::system;
using namespace mrpt::opengl;
using namespace std;

/*-------------------------------------------------------------
						Constructor
-------------------------------------------------------------*/
CRoboPeakLidar::CRoboPeakLidar() :
	m_com_port(""),
	m_com_port_baudrate(115200),
	m_rplidar_drv(NULL)
{
	m_sensorLabel = "RPLidar";
}

/*-------------------------------------------------------------
					~CRoboPeakLidar
-------------------------------------------------------------*/
CRoboPeakLidar::~CRoboPeakLidar()
{
	turnOff();
	disconnect();
}

void CRoboPeakLidar::disconnect()
{
#if MRPT_HAS_ROBOPEAK_LIDAR
	RPlidarDriver::DisposeDriver(RPLIDAR_DRV);
	m_rplidar_drv=NULL;
#endif
}

/*-------------------------------------------------------------
						doProcessSimple
-------------------------------------------------------------*/
void  CRoboPeakLidar::doProcessSimple(
		bool							&outThereIsObservation,
		mrpt::slam::CObservation2DRangeScan	&outObservation,
		bool							&hardwareError )
{
#if MRPT_HAS_ROBOPEAK_LIDAR
	outThereIsObservation	= false;
	hardwareError			= false;

	// Bound?
	if (!checkCOMMs())
	{
		hardwareError = true;
		return;
	}

	rplidar_response_measurement_node_t nodes[360*2];
	size_t   count = sizeof(nodes)/sizeof(nodes[0]);

	// Scan:
	const mrpt::system::TTimeStamp tim_scan_start = mrpt::system::now();
	u_result op_result = RPLIDAR_DRV->grabScanData(nodes, count);
	//const mrpt::system::TTimeStamp tim_scan_end = mrpt::system::now();
	//const double scan_duration = mrpt::system::timeDifference(tim_scan_start,tim_scan_end);

	// Fill in scan data:
	if (op_result == RESULT_OK)
	{
		op_result = RPLIDAR_DRV->ascendScanData(nodes, count);
		if (op_result == RESULT_OK)
		{
			const size_t angle_compensate_nodes_count = 360;
			const size_t angle_compensate_multiple = 1;
			int angle_compensate_offset = 0;
			rplidar_response_measurement_node_t angle_compensate_nodes[angle_compensate_nodes_count];
			memset(angle_compensate_nodes, 0, angle_compensate_nodes_count*sizeof(rplidar_response_measurement_node_t));

			outObservation.scan.assign(count, 0);
			outObservation.validRange.resize(count, 0);

			for(size_t i=0 ; i < count; i++ )
			{
				if (nodes[i].distance_q2 != 0)
				{
					float angle = (float)((nodes[i].angle_q6_checkbit >> RPLIDAR_RESP_MEASUREMENT_ANGLE_SHIFT)/64.0f);
					int angle_value = (int)(angle * angle_compensate_multiple);
					if ((angle_value - angle_compensate_offset) < 0) angle_compensate_offset = angle_value;
					for (size_t j = 0; j < angle_compensate_multiple; j++)
					{
						angle_compensate_nodes[angle_value-angle_compensate_offset+j] = nodes[i];
					}
				}
			}

			for(size_t i=0 ; i < count; i++ )
			{
				const float read_value = (float) angle_compensate_nodes[i].distance_q2/4.0f/1000;
				outObservation.scan[i] = read_value;
				outObservation.validRange[i] = (read_value>0);
			}
		}
		else if (op_result == RESULT_OPERATION_FAIL)
		{
			// All the data is invalid, just publish them
			outObservation.scan.assign(count, 0);
			outObservation.validRange.resize(count, 0);
		}

		// Fill common parts of the obs:
		outObservation.timestamp = tim_scan_start;
		outObservation.rightToLeft = false;
		outObservation.aperture = 2.0*M_PI;
		outObservation.maxRange	= 6.0;
		outObservation.stdError = 0.010f;
		outObservation.sensorPose = m_sensorPose;
		outObservation.sensorLabel = m_sensorLabel;

		// Do filter:
		C2DRangeFinderAbstract::filterByExclusionAreas( outObservation );
		C2DRangeFinderAbstract::filterByExclusionAngles( outObservation );
		// Do show preview:
		C2DRangeFinderAbstract::processPreview(outObservation);

		outThereIsObservation = true;
	}
	else
	{
		if (op_result==RESULT_OPERATION_TIMEOUT || op_result==RESULT_OPERATION_FAIL)
		{
			// Error? Retry connection
			this->disconnect();
		}
	}

#endif
}

/*-------------------------------------------------------------
						loadConfig_sensorSpecific
-------------------------------------------------------------*/
void  CRoboPeakLidar::loadConfig_sensorSpecific(
		const mrpt::utils::CConfigFileBase &configSource,
		const std::string	  &iniSection )
{
	m_sensorPose.setFromValues(
				configSource.read_float(iniSection,"pose_x",0),
				configSource.read_float(iniSection,"pose_y",0),
				configSource.read_float(iniSection,"pose_z",0),
				DEG2RAD( configSource.read_float(iniSection,"pose_yaw",0) ),
				DEG2RAD( configSource.read_float(iniSection,"pose_pitch",0) ),
				DEG2RAD( configSource.read_float(iniSection,"pose_roll",0) )
				);

#ifdef MRPT_OS_WINDOWS
	m_com_port = configSource.read_string(iniSection, "COM_port_WIN", m_com_port, true );
#else
	m_com_port = configSource.read_string(iniSection, "COM_port_LIN", m_com_port, true );
#endif

	// Parent options:
	this->loadCommonParams(configSource,iniSection);
}

/*-------------------------------------------------------------
						turnOn
-------------------------------------------------------------*/
bool  CRoboPeakLidar::turnOn()
{
	return checkCOMMs();
}

/*-------------------------------------------------------------
						turnOff
-------------------------------------------------------------*/
bool  CRoboPeakLidar::turnOff()
{
#if MRPT_HAS_ROBOPEAK_LIDAR
	if (RPLIDAR_DRV) RPLIDAR_DRV->stop();
	return true;
#else
	THROW_EXCEPTION("MRPT has been compiled without RPLidar support!")
		#endif
}

/** Returns true if the device is connected & operative */
bool CRoboPeakLidar::getDeviceHealth() const
{
#if MRPT_HAS_ROBOPEAK_LIDAR
	if (!RPLIDAR_DRV) return false;

	rplidar_response_device_health_t healthinfo;

	u_result op_result = RPLIDAR_DRV->getHealth(healthinfo);
	if (IS_OK(op_result))
	{
		printf("[CRoboPeakLidar] RPLidar health status : %d\n", healthinfo.status);
		if (healthinfo.status != RPLIDAR_STATUS_OK)
		{
			fprintf(stderr, "[CRoboPeakLidar] Error, rplidar internal error detected. Please reboot the device to retry.\n");
			return false;
		}
	}
	else
	{
		fprintf(stderr, "[CRoboPeakLidar] Error, cannot retrieve rplidar health code: %x\n", op_result);
		return false;
	}

	return true;
#else
	THROW_EXCEPTION("MRPT has been compiled without RPLidar support!")
		#endif
}

/*-------------------------------------------------------------
						checkCOMMs
-------------------------------------------------------------*/
bool  CRoboPeakLidar::checkCOMMs()
{
	MRPT_START
		#if MRPT_HAS_ROBOPEAK_LIDAR
			if (RPLIDAR_DRV)
			return true;

	// create the driver instance
	m_rplidar_drv = RPlidarDriver::CreateDriver(RPlidarDriver::DRIVER_TYPE_SERIALPORT);
	ASSERTMSG_(m_rplidar_drv, "Create Driver failed.")

			// Is it COMX, X>4? ->  "\\.\COMX"
			if (m_com_port.size()>=3)
	{
		if ( tolower( m_com_port[0]) =='c' && tolower( m_com_port[1]) =='o' && tolower( m_com_port[2]) =='m' )
		{
			// Need to add "\\.\"?
			if (m_com_port.size()>4 || m_com_port[3]>'4')
				m_com_port = std::string("\\\\.\\") + m_com_port;
		}
	}

	// make connection...
	if (IS_FAIL(RPLIDAR_DRV->connect( m_com_port.c_str(), (_u32)m_com_port_baudrate)))
	{
		fprintf(stderr, "[CRoboPeakLidar] Error, cannot bind to the specified serial port %s\n",  m_com_port.c_str() );
		return false;
	}

	rplidar_response_device_info_t devinfo;
	if (IS_FAIL(RPLIDAR_DRV->getDeviceInfo(devinfo) ))
	{
		return false;
	}

	if (m_verbose)
	{
		printf("[CRoboPeakLidar] Connection established:\n"
			   "Firmware version: %u\n"
			   "Hardware version: %u\n"
			   "Model: %u\n"
			   "Serial: ",
			   (unsigned int)devinfo.firmware_version,
			   (unsigned int)devinfo.hardware_version,
			   (unsigned int)devinfo.model);

		for (int i=0;i<16;i++)
			printf("%02X",devinfo.serialnum[i]);
		printf("\n");
	}

	// check health:
	if (!getDeviceHealth())
		return false;

	// start scan...
	u_result res = RPLIDAR_DRV->startScan();
	if (IS_FAIL( res ))
	{
		fprintf(stderr, "[CRoboPeakLidar] Error starting scanning mode: %x\n", res);
		return false;
	}

	return true;
#else
			THROW_EXCEPTION("MRPT has been compiled without RPLidar support!")
		#endif
			MRPT_END
}

/*-------------------------------------------------------------
						initialize
-------------------------------------------------------------*/
void CRoboPeakLidar::initialize()
{
	if (!checkCOMMs()) return;

	if (!turnOn())
	{
		cerr << "[CRoboPeakLidar::initialize] Error initializing RPLIDAR scanner" << endl;
		return;
	}

}

void CRoboPeakLidar::setSerialPort(const std::string &port_name)
{
	if (m_rplidar_drv)
		THROW_EXCEPTION("Can't change serial port while connected!")

				m_com_port = port_name;
}

<|endoftext|>


<commit_before>//#include "stdafx.h"
#include <iostream>
//#include <conio.h>
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include <string>
#include <sstream>

double alpha = 2.0; /**< Simple contrast control */
int beta = 3;  /**< Simple brightness control */

int HighR = 255;
int LowR = 0;
int HighG = 255;
int LowG = 0;
int HighB = 255;
int LowB = 0;

double iLastX = -1;
double iLastY = -1;

using namespace cv;
using namespace std;

int main(int argc, char** argv)
{
	VideoCapture cap(0); //capture the video from webcam

	cap.set(CV_CAP_PROP_FRAME_WIDTH, 640);
    cap.set(CV_CAP_PROP_FRAME_HEIGHT, 480);

	if (!cap.isOpened())  // if not success, exit program
	{
		cout << "Cannot open the web cam" << endl;
		return -1;
	}
	namedWindow("Control", CV_WINDOW_AUTOSIZE); //create a window called "Control"
	//Create trackbars in "Control" window
	createTrackbar("LowR", "Control", &LowR, 255); //Hue (0 - 179)
	createTrackbar("HighR", "Control", &HighR, 255);
	createTrackbar("LowG", "Control", &LowG, 255); //Hue (0 - 179)
	createTrackbar("HighG", "Control", &HighG, 255);
	createTrackbar("LowB", "Control", &LowB, 255); //Hue (0 - 179)
	createTrackbar("HighB", "Control", &HighB, 255);
    createTrackbar("Beta", "Control",&beta, 200);

	//Capture a temporary image from the camera
	Mat imgTmp;
	cap.read(imgTmp);	//Create a black image with the size as the camera output
	Mat imgLines = Mat::zeros(imgTmp.size(), CV_8UC3);
	while (true)
	{
		Mat imgOriginal;
		bool bSuccess = cap.read(imgOriginal); // read a new frame from video
		if (!bSuccess) //if not success, break loop
		{
			cout << "Cannot read a frame from video stream" << endl;
			break;
		}

		for (int y = 0; y < imgOriginal.rows; y++){
			for (int x = 0; x < imgOriginal.cols; x++){
				for (int c = 0; c < 3; c++){
					imgOriginal.at<Vec3b>(y, x)[c] =
					saturate_cast<uchar>(alpha*(imgOriginal.at<Vec3b>(y, x)[c]) + beta);
				}
			}
		}

		Mat imgHSV = imgOriginal;
		GaussianBlur(imgOriginal, imgOriginal, Size(0, 0), 3);
		//cvtColor(imgOriginal, imgHSV, COLOR_BGR2HSV); //Convert the captured frame from BGR to HSV
		Mat imgThresholded;
		inRange(imgHSV, Scalar(LowB, LowG, LowR), Scalar(HighB, HighG, HighR), imgThresholded); //Threshold the image
		//morphological opening (removes small objects from the foreground)
		erode(imgThresholded, imgThresholded, getStructuringElement(MORPH_ELLIPSE, Size(5, 5)));
		dilate(imgThresholded, imgThresholded, getStructuringElement(MORPH_ELLIPSE, Size(5, 5)));
		//morphological closing (removes small holes from the foreground)
		dilate(imgThresholded, imgThresholded, getStructuringElement(MORPH_ELLIPSE, Size(5, 5)));
		erode(imgThresholded, imgThresholded, getStructuringElement(MORPH_ELLIPSE, Size(5, 5)));
		//Calculate the moments of the thresholded image
		Moments oMoments = moments(imgThresholded);
		int dM01 = oMoments.m01;
		int dM10 = oMoments.m10;
		double dArea = oMoments.m00;

		// if the area <= 20000, I consider that the there are no object in the image and it's because of the noise, the area is not zero
		if (dArea > 20000)
		{
			//calculate the position of the ball
			int posX = dM10 / dArea;
			int posY = dM01 / dArea;
			circle(imgOriginal, Point(posX, posY), 30, Scalar(0, 0, 255), 2);
			circle(imgOriginal, Point(posX, posY), 5, Scalar(0, 255, 0), 2);

			if (iLastX >= 0 && iLastY >= 0 && posX >= 0 && posY >= 0)
			{
				//Draw a red line from the previous point to the current point		B, G, R     Diamiter
				//	line(imgLines, Point(posX, posY), Point(iLastX, iLastY), Scalar(0, 0, 255), 2);  here is the line
			}
			iLastX = posX;
			iLastY = posY;
			std::cout << posX << ", " << posY << std::endl;
			std::cout << std::endl;
			std::cout << "B: " << LowB << ", " << HighB << std::endl;
			std::cout << "G: " << LowG << ", " << HighG << std::endl;
			std::cout << "R: " << LowR << ", " << HighR << std::endl;
 			std::cout << "Beta: " << beta << std::endl;

		}

		imgOriginal = imgOriginal + imgLines;
		Mat outOriginal = imgOriginal;
		flip(outOriginal, outOriginal, 1);

		imshow("Control", imgThresholded); //show the thresholded image
		imshow("Original", outOriginal);
		//show the original image
		//imshow("HSV", imgHSV);

		if (waitKey(30) == 27) //wait for 'esc' key press for 30ms. If 'esc' key is pressed, break loop
		{
			cout << "esc key is pressed by user" << endl;
			break;
		}
	}
	return 0;
}<commit_msg>ok i think i got it<commit_after>//#include "stdafx.h"
#include <iostream>
//#include <conio.h>
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include <string>
#include <sstream>

double alpha = 2.0; /**< Simple contrast control */
int beta = 3;  /**< Simple brightness control */

int HighR = 255;
int LowR = 0;
int HighG = 255;
int LowG = 0;
int HighB = 255;
int LowB = 0;

double iLastX = -1;
double iLastY = -1;

using namespace cv;
using namespace std;

int main(int argc, char** argv)
{
	VideoCapture cap(0); //capture the video from webcam

	cap.set(CV_CAP_PROP_FRAME_WIDTH, 640);
    cap.set(CV_CAP_PROP_FRAME_HEIGHT, 480);

	if (!cap.isOpened())  // if not success, exit program
	{
		cout << "Cannot open the web cam" << endl;
		return -1;
	}
	namedWindow("Control", CV_WINDOW_AUTOSIZE); //create a window called "Control"
	//Create trackbars in "Control" window
	createTrackbar("LowR", "Control", &LowR, 255); //Hue (0 - 179)
	createTrackbar("HighR", "Control", &HighR, 255);
	createTrackbar("LowG", "Control", &LowG, 255); //Hue (0 - 179)
	createTrackbar("HighG", "Control", &HighG, 255);
	createTrackbar("LowB", "Control", &LowB, 255); //Hue (0 - 179)
	createTrackbar("HighB", "Control", &HighB, 255);
    createTrackbar("Beta", "Control",&beta, 200);

	//Capture a temporary image from the camera
	Mat imgTmp;
	cap.read(imgTmp);	//Create a black image with the size as the camera output
	Mat imgLines = Mat::zeros(imgTmp.size(), CV_8UC3);
	while (true)
	{
		Mat imgOriginal;
		bool bSuccess = cap.read(imgOriginal); // read a new frame from video
		if (!bSuccess) //if not success, break loop
		{
			cout << "Cannot read a frame from video stream" << endl;
			break;
		}

		for (int y = 0; y < imgOriginal.rows; y++){
			for (int x = 0; x < imgOriginal.cols; x++){
				for (int c = 0; c < 3; c++){
					imgOriginal.at<Vec3b>(y, x)[c] =
					saturate_cast<uchar>(alpha*(imgOriginal.at<Vec3b>(y, x)[c]) + beta);
				}
			}
		}

		Mat imgHSV = imgOriginal;
		GaussianBlur(imgOriginal, imgOriginal, Size(0, 0), 3);
		//cvtColor(imgOriginal, imgHSV, COLOR_BGR2HSV); //Convert the captured frame from BGR to HSV
		Mat imgThresholded;
		inRange(imgHSV, Scalar(LowB, LowG, LowR), Scalar(HighB, HighG, HighR), imgThresholded); //Threshold the image
		//morphological opening (removes small objects from the foreground)
		erode(imgThresholded, imgThresholded, getStructuringElement(MORPH_ELLIPSE, Size(5, 5)));
		dilate(imgThresholded, imgThresholded, getStructuringElement(MORPH_ELLIPSE, Size(5, 5)));
		//morphological closing (removes small holes from the foreground)
		dilate(imgThresholded, imgThresholded, getStructuringElement(MORPH_ELLIPSE, Size(5, 5)));
		erode(imgThresholded, imgThresholded, getStructuringElement(MORPH_ELLIPSE, Size(5, 5)));
		//Calculate the moments of the thresholded image
		Moments oMoments = moments(imgThresholded);
		int dM01 = oMoments.m01;
		int dM10 = oMoments.m10;
		double dArea = oMoments.m00;

		// if the area <= 20000, I consider that the there are no object in the image and it's because of the noise, the area is not zero
		if (dArea > 20000)
		{
			//calculate the position of the ball
			int posX = dM10 / dArea;
			int posY = dM01 / dArea;
			circle(imgOriginal, Point(posX, posY), 30, Scalar(0, 0, 255), 2);
			circle(imgOriginal, Point(posX, posY), 5, Scalar(0, 255, 0), 2);

			if (iLastX >= 0 && iLastY >= 0 && posX >= 0 && posY >= 0)
			{
				//Draw a red line from the previous point to the current point		B, G, R     Diamiter
				//	line(imgLines, Point(posX, posY), Point(iLastX, iLastY), Scalar(0, 0, 255), 2);  here is the line
			}
			iLastX = posX;
			iLastY = posY;
			std::cout << posX << ", " << posY << std::endl;
			std::cout << std::endl;
			std::cout << "B: " << LowB << ", " << HighB << std::endl;
			std::cout << "G: " << LowG << ", " << HighG << std::endl;
			std::cout << "R: " << LowR << ", " << HighR << std::endl;
 			std::cout << "Beta: " << beta << std::endl;

		}
        //ok
		imgOriginal = imgOriginal + imgLines;
		Mat outOriginal = imgOriginal;
		flip(outOriginal, outOriginal, 1);

		imshow("Control", imgThresholded); //show the thresholded image
		imshow("Original", outOriginal);
		//show the original image
		//imshow("HSV", imgHSV);

		if (waitKey(30) == 27) //wait for 'esc' key press for 30ms. If 'esc' key is pressed, break loop
		{
			cout << "esc key is pressed by user" << endl;
			break;
		}
	}
	return 0;
}<|endoftext|>