<commit_before>#include <QFileInfo>

#include <coreplugin/editormanager/editormanager.h>
#include <projectexplorer/runconfiguration.h>
#include <projectexplorer/target.h>
#include <projectexplorer/buildconfiguration.h>
#include <projectexplorer/project.h>

#include "OutputPane.h"
#include "OutputParser.h"
#include "PaneWidget.h"
#include "TestModel.h"
#include "ParseState.h"
#include "TestMark.h"

using namespace QtcGtest::Internal;

OutputPane::OutputPane(QObject *parent) :
  IOutputPane(parent),
  parser_ (new OutputParser),
  model_ (new TestModel),
  state_ (new ParseState),
  widget_ (NULL),
  totalsLabel_ (new QLabel),
  disabledLabel_ (new QLabel),
  togglePopupButton_ (new QToolButton),
  togglePassedButton_ (new QToolButton)
{
  totalsLabel_->setMargin(5);

  togglePopupButton_->setCheckable (true);
  togglePopupButton_->setChecked (true);
  togglePopupButton_->setToolTip (tr ("Auto popup pane"));
  togglePopupButton_->setIcon(QIcon(QLatin1String(":/images/popup.ico")));

  togglePassedButton_->setCheckable (true);
  togglePassedButton_->setChecked (true);
  togglePassedButton_->setToolTip (tr ("Show passed tests"));
  togglePassedButton_->setIcon(QIcon(QLatin1String(":/images/passed.ico")));

  connect (model_.data (), &TestModel::newError, this, &OutputPane::addMark);
}

OutputPane::~OutputPane()
{
  delete togglePassedButton_;
  delete togglePopupButton_;
  delete disabledLabel_;
  delete totalsLabel_;
  delete parser_;
  delete state_;
}

QWidget *OutputPane::outputWidget(QWidget *parent)
{
  Q_ASSERT (model_ != NULL);
  widget_ = new PaneWidget (model_, parent); // Can be only 1?
  connect (widget_.data (), SIGNAL (viewClicked (const QModelIndex&)),
           this, SLOT (handleViewClicked (const QModelIndex&)));
  connect (togglePassedButton_, SIGNAL (clicked (bool)),
           widget_.data (), SLOT (showPassed (bool)));
  return widget_.data ();
}

QList<QWidget *> OutputPane::toolBarWidgets() const
{
  QList<QWidget*> widgets;
  widgets << togglePopupButton_ << togglePassedButton_ << totalsLabel_ << disabledLabel_;
  return widgets;
}

QString OutputPane::displayName() const
{
  return tr ("Google Test");
}

int OutputPane::priorityInStatusBar() const
{
  return 10;
}

void OutputPane::clearContents()
{
  qDeleteAll (marks);
  marks.clear ();
  model_->clear ();
  totalsLabel_->clear ();
  disabledLabel_->clear ();
}

void OutputPane::visibilityChanged(bool visible)
{
}

void OutputPane::setFocus()
{
  if (!widget_.isNull ())
  {
    widget_->setFocus ();
  }
}

bool OutputPane::hasFocus() const
{
  if (!widget_.isNull ())
  {
    return widget_->hasFocus ();
  }
  return false;
}

bool OutputPane::canFocus() const
{
  return (!widget_.isNull ());
}

bool OutputPane::canNavigate() const
{
  return true;
}

bool OutputPane::canNext() const
{
  Q_ASSERT (model_ != NULL);
  // Do not update value because Creator checks it BEFORE it can actually be updated.
  return (model_->errorCount () > 0);
}

bool OutputPane::canPrevious() const
{
  Q_ASSERT (model_ != NULL);
  // Do not update value because Creator checks it BEFORE it can actually be updated.
  return (model_->errorCount () > 0);
}

void OutputPane::goToNext()
{
  Q_ASSERT (!widget_.isNull ());
  QModelIndex currentIndex = widget_->testModelIndex (widget_->currentIndex ());
  showError (model_->nextError (currentIndex));
}

void OutputPane::goToPrev()
{
  Q_ASSERT (!widget_.isNull ());
  QModelIndex currentIndex = widget_->testModelIndex (widget_->currentIndex ());
  showError (model_->previousError (currentIndex));
}

void OutputPane::setCurrentIndex(const QModelIndex &index)
{
  widget_->setCurrentIndex (widget_->proxyIndex(index));
}

void OutputPane::showError(const QModelIndex &errorIndex)
{
  if (!errorIndex.isValid ())
  {
    return;
  }
  widget_->setCurrentIndex (widget_->proxyIndex(errorIndex));
  int row = errorIndex.row ();
  QString file = errorIndex.sibling (row, TestModel::ColumnFile).data ().toString ();
  int line = errorIndex.sibling (row, TestModel::ColumnLine).data ().toInt ();
  Core::EditorManager::openEditorAt (file, line);
}

void OutputPane::handleViewClicked(const QModelIndex &index)
{
  Q_ASSERT (index.isValid());
  QModelIndex sourceIndex = widget_->testModelIndex (index);
  TestModel::Type type = model_->getType (sourceIndex);
  if (type == TestModel::TypeDetailError)
  {
    showError (sourceIndex);
  }
  else if (type == TestModel::TypeDetail)
  {
    QModelIndex previousError = model_->previousError (sourceIndex);
    if (previousError.isValid () && previousError.parent ().row () == sourceIndex.parent ().row ())
    {
      showError (model_->previousError (sourceIndex));
    }
  }
}

void OutputPane::addMark(const QModelIndex &index)
{
  auto row = index.row ();
  auto file = index.sibling (row, TestModel::ColumnFile).data ().toString ();
  auto line = index.sibling (row, TestModel::ColumnLine).data ().toInt ();
  marks << new TestMark (QPersistentModelIndex(index), file, line, *this);
}

void OutputPane::handleRunStart(ProjectExplorer::RunControl *control)
{
  state_->reset ();
  model_->clear ();
  totalsLabel_->clear ();
  disabledLabel_->clear ();
  state_->projectFiles = control->project ()->files (ProjectExplorer::Project::SourceFiles);
  connect (control, SIGNAL (appendMessage(ProjectExplorer::RunControl *, const QString &, Utils::OutputFormat )),
           this, SLOT (parseMessage(ProjectExplorer::RunControl *, const QString &, Utils::OutputFormat )));

}

void OutputPane::handleRunFinish (ProjectExplorer::RunControl *control)
{
  if (state_->isGoogleTestRun)
  {
    widget_->spanColumns ();
    totalsLabel_->setText (tr ("Total: passed %1 of %2 (%3 ms).").arg (
                             state_->passedTotalCount).arg (
                             state_->passedTotalCount +
                             state_->failedTotalCount).arg (state_->totalTime));
    disabledLabel_->setText(tr ("Disabled tests: %1.").arg (state_->disabledCount));
    if (togglePopupButton_->isChecked())
    {
      popup (WithFocus);
    }
  }
  disconnect (control, SIGNAL (appendMessage(ProjectExplorer::RunControl *, const QString &, Utils::OutputFormat )),
              this, SLOT (parseMessage(ProjectExplorer::RunControl *, const QString &, Utils::OutputFormat )));

}

void OutputPane::parseMessage(ProjectExplorer::RunControl *control, const QString &msg, Utils::OutputFormat format)
{
  Q_UNUSED (control);
  if (!(format == Utils::StdOutFormat || format == Utils::StdOutFormatSameLine))
  {
    return;
  }

  QStringList lines = msg.split (QLatin1Char ('\n'));
  foreach (const QString& line, lines)
  {
    if (line.trimmed ().isEmpty ())
    {
      continue;
    }
    if (!state_->isGoogleTestRun)
    {
      state_->isGoogleTestRun = parser_->isGoogleTestRun (line);
      if (!state_->isGoogleTestRun) {
        continue;
      }
    }
    parser_->parseMessage (line, *model_, *state_);
  }
}
<commit_msg>Check variables for existence.<commit_after>#include <QFileInfo>

#include <coreplugin/editormanager/editormanager.h>
#include <projectexplorer/runconfiguration.h>
#include <projectexplorer/target.h>
#include <projectexplorer/buildconfiguration.h>
#include <projectexplorer/project.h>

#include "OutputPane.h"
#include "OutputParser.h"
#include "PaneWidget.h"
#include "TestModel.h"
#include "ParseState.h"
#include "TestMark.h"

using namespace QtcGtest::Internal;

OutputPane::OutputPane(QObject *parent) :
  IOutputPane(parent),
  parser_ (new OutputParser),
  model_ (new TestModel),
  state_ (new ParseState),
  widget_ (NULL),
  totalsLabel_ (new QLabel),
  disabledLabel_ (new QLabel),
  togglePopupButton_ (new QToolButton),
  togglePassedButton_ (new QToolButton)
{
  totalsLabel_->setMargin(5);

  togglePopupButton_->setCheckable (true);
  togglePopupButton_->setChecked (true);
  togglePopupButton_->setToolTip (tr ("Auto popup pane"));
  togglePopupButton_->setIcon(QIcon(QLatin1String(":/images/popup.ico")));

  togglePassedButton_->setCheckable (true);
  togglePassedButton_->setChecked (true);
  togglePassedButton_->setToolTip (tr ("Show passed tests"));
  togglePassedButton_->setIcon(QIcon(QLatin1String(":/images/passed.ico")));

  connect (model_.data (), &TestModel::newError, this, &OutputPane::addMark);
}

OutputPane::~OutputPane()
{
  delete togglePassedButton_;
  delete togglePopupButton_;
  delete disabledLabel_;
  delete totalsLabel_;
  delete parser_;
  delete state_;
}

QWidget *OutputPane::outputWidget(QWidget *parent)
{
  Q_ASSERT (model_ != NULL);
  widget_ = new PaneWidget (model_, parent); // Can be only 1?
  connect (widget_.data (), SIGNAL (viewClicked (const QModelIndex&)),
           this, SLOT (handleViewClicked (const QModelIndex&)));
  connect (togglePassedButton_, SIGNAL (clicked (bool)),
           widget_.data (), SLOT (showPassed (bool)));
  return widget_.data ();
}

QList<QWidget *> OutputPane::toolBarWidgets() const
{
  QList<QWidget*> widgets;
  widgets << togglePopupButton_ << togglePassedButton_ << totalsLabel_ << disabledLabel_;
  return widgets;
}

QString OutputPane::displayName() const
{
  return tr ("Google Test");
}

int OutputPane::priorityInStatusBar() const
{
  return 10;
}

void OutputPane::clearContents()
{
  qDeleteAll (marks);
  marks.clear ();
  model_->clear ();
  totalsLabel_->clear ();
  disabledLabel_->clear ();
}

void OutputPane::visibilityChanged(bool visible)
{
}

void OutputPane::setFocus()
{
  if (!widget_.isNull ())
  {
    widget_->setFocus ();
  }
}

bool OutputPane::hasFocus() const
{
  if (!widget_.isNull ())
  {
    return widget_->hasFocus ();
  }
  return false;
}

bool OutputPane::canFocus() const
{
  return (!widget_.isNull ());
}

bool OutputPane::canNavigate() const
{
  return true;
}

bool OutputPane::canNext() const
{
  Q_ASSERT (model_ != NULL);
  // Do not update value because Creator checks it BEFORE it can actually be updated.
  return (model_->errorCount () > 0);
}

bool OutputPane::canPrevious() const
{
  Q_ASSERT (model_ != NULL);
  // Do not update value because Creator checks it BEFORE it can actually be updated.
  return (model_->errorCount () > 0);
}

void OutputPane::goToNext()
{
  Q_ASSERT (!widget_.isNull ());
  QModelIndex currentIndex = widget_->testModelIndex (widget_->currentIndex ());
  showError (model_->nextError (currentIndex));
}

void OutputPane::goToPrev()
{
  Q_ASSERT (!widget_.isNull ());
  QModelIndex currentIndex = widget_->testModelIndex (widget_->currentIndex ());
  showError (model_->previousError (currentIndex));
}

void OutputPane::setCurrentIndex(const QModelIndex &index)
{
  widget_->setCurrentIndex (widget_->proxyIndex(index));
}

void OutputPane::showError(const QModelIndex &errorIndex)
{
  if (!errorIndex.isValid ())
  {
    return;
  }
  widget_->setCurrentIndex (widget_->proxyIndex(errorIndex));
  int row = errorIndex.row ();
  QString file = errorIndex.sibling (row, TestModel::ColumnFile).data ().toString ();
  int line = errorIndex.sibling (row, TestModel::ColumnLine).data ().toInt ();
  Core::EditorManager::openEditorAt (file, line);
}

void OutputPane::handleViewClicked(const QModelIndex &index)
{
  Q_ASSERT (index.isValid());
  QModelIndex sourceIndex = widget_->testModelIndex (index);
  TestModel::Type type = model_->getType (sourceIndex);
  if (type == TestModel::TypeDetailError)
  {
    showError (sourceIndex);
  }
  else if (type == TestModel::TypeDetail)
  {
    QModelIndex previousError = model_->previousError (sourceIndex);
    if (previousError.isValid () && previousError.parent ().row () == sourceIndex.parent ().row ())
    {
      showError (model_->previousError (sourceIndex));
    }
  }
}

void OutputPane::addMark(const QModelIndex &index)
{
  auto row = index.row ();
  auto file = index.sibling (row, TestModel::ColumnFile).data ().toString ();
  auto line = index.sibling (row, TestModel::ColumnLine).data ().toInt ();
  marks << new TestMark (QPersistentModelIndex(index), file, line, *this);
}

void OutputPane::handleRunStart(ProjectExplorer::RunControl *control)
{
  state_->reset ();
  model_->clear ();
  totalsLabel_->clear ();
  disabledLabel_->clear ();
  if (control && control->project ()) {
    state_->projectFiles = control->project ()->files (ProjectExplorer::Project::SourceFiles);
  }
  connect (control, SIGNAL (appendMessage(ProjectExplorer::RunControl *, const QString &, Utils::OutputFormat )),
           this, SLOT (parseMessage(ProjectExplorer::RunControl *, const QString &, Utils::OutputFormat )));

}

void OutputPane::handleRunFinish (ProjectExplorer::RunControl *control)
{
  if (state_->isGoogleTestRun)
  {
    widget_->spanColumns ();
    totalsLabel_->setText (tr ("Total: passed %1 of %2 (%3 ms).").arg (
                             state_->passedTotalCount).arg (
                             state_->passedTotalCount +
                             state_->failedTotalCount).arg (state_->totalTime));
    disabledLabel_->setText(tr ("Disabled tests: %1.").arg (state_->disabledCount));
    if (togglePopupButton_->isChecked())
    {
      popup (WithFocus);
    }
  }
  disconnect (control, SIGNAL (appendMessage(ProjectExplorer::RunControl *, const QString &, Utils::OutputFormat )),
              this, SLOT (parseMessage(ProjectExplorer::RunControl *, const QString &, Utils::OutputFormat )));

}

void OutputPane::parseMessage(ProjectExplorer::RunControl *control, const QString &msg, Utils::OutputFormat format)
{
  Q_UNUSED (control);
  if (!(format == Utils::StdOutFormat || format == Utils::StdOutFormatSameLine))
  {
    return;
  }

  QStringList lines = msg.split (QLatin1Char ('\n'));
  foreach (const QString& line, lines)
  {
    if (line.trimmed ().isEmpty ())
    {
      continue;
    }
    if (!state_->isGoogleTestRun)
    {
      state_->isGoogleTestRun = parser_->isGoogleTestRun (line);
      if (!state_->isGoogleTestRun) {
        continue;
      }
    }
    parser_->parseMessage (line, *model_, *state_);
  }
}
<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  $RCSfile: ignoreZiZu_ja_JP.cxx,v $
 *
 *  $Revision: 1.6 $
 *
 *  last change: $Author: hr $ $Date: 2003-04-28 16:53:19 $
 *
 *  The Contents of this file are made available subject to the terms of
 *  either of the following licenses
 *
 *         - GNU Lesser General Public License Version 2.1
 *         - Sun Industry Standards Source License Version 1.1
 *
 *  Sun Microsystems Inc., October, 2000
 *
 *  GNU Lesser General Public License Version 2.1
 *  =============================================
 *  Copyright 2000 by Sun Microsystems, Inc.
 *  901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License version 2.1, as published by the Free Software Foundation.
 *
 *  This library is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *  Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this library; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *  MA  02111-1307  USA
 *
 *
 *  Sun Industry Standards Source License Version 1.1
 *  =================================================
 *  The contents of this file are subject to the Sun Industry Standards
 *  Source License Version 1.1 (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.openoffice.org/license.html.
 *
 *  Software provided under this License is provided on an "AS IS" basis,
 *  WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
 *  WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
 *  MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
 *  See the License for the specific provisions governing your rights and
 *  obligations concerning the Software.
 *
 *  The Initial Developer of the Original Code is: Sun Microsystems, Inc.
 *
 *  Copyright: 2000 by Sun Microsystems, Inc.
 *
 *  All Rights Reserved.
 *
 *  Contributor(s): _______________________________________
 *
 *
 ************************************************************************/

// prevent internal compiler error with MSVC6SP3
#include <utility>

#define TRANSLITERATION_ZiZu_ja_JP
#include <transliteration_Ignore.hxx>

namespace com { namespace sun { namespace star { namespace i18n {

sal_Unicode
ignoreZiZu_ja_JP_translator (const sal_Unicode c)
{

    switch (c) {
        case 0x30C2:     // KATAKANA LETTER DI
            return 0x30B8; // KATAKANA LETTER ZI

        case 0x3062:     // HIRAGANA LETTER DI
            return 0x3058; // HIRAGANA LETTER ZI

        case 0x30C5:     // KATAKANA LETTER DU
            return 0x30BA; // KATAKANA LETTER ZU

        case 0x3065:     // HIRAGANA LETTER DU
            return 0x305A; // HIRAGANA LETTER ZU
    }
    return c;
}

ignoreZiZu_ja_JP::ignoreZiZu_ja_JP()
{
        func = ignoreZiZu_ja_JP_translator;
        table = 0;
        map = 0;
        transliterationName = "ignoreZiZu_ja_JP";
        implementationName = "com.sun.star.i18n.Transliteration.ignoreZiZu_ja_JP";
}

} } } }
<commit_msg>INTEGRATION: CWS ooo19126 (1.6.190); FILE MERGED 2005/09/05 17:47:58 rt 1.6.190.1: #i54170# Change license header: remove SISSL<commit_after>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: ignoreZiZu_ja_JP.cxx,v $
 *
 *  $Revision: 1.7 $
 *
 *  last change: $Author: rt $ $Date: 2005-09-07 17:32:27 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/

// prevent internal compiler error with MSVC6SP3
#include <utility>

#define TRANSLITERATION_ZiZu_ja_JP
#include <transliteration_Ignore.hxx>

namespace com { namespace sun { namespace star { namespace i18n {

sal_Unicode
ignoreZiZu_ja_JP_translator (const sal_Unicode c)
{

    switch (c) {
        case 0x30C2:     // KATAKANA LETTER DI
            return 0x30B8; // KATAKANA LETTER ZI

        case 0x3062:     // HIRAGANA LETTER DI
            return 0x3058; // HIRAGANA LETTER ZI

        case 0x30C5:     // KATAKANA LETTER DU
            return 0x30BA; // KATAKANA LETTER ZU

        case 0x3065:     // HIRAGANA LETTER DU
            return 0x305A; // HIRAGANA LETTER ZU
    }
    return c;
}

ignoreZiZu_ja_JP::ignoreZiZu_ja_JP()
{
        func = ignoreZiZu_ja_JP_translator;
        table = 0;
        map = 0;
        transliterationName = "ignoreZiZu_ja_JP";
        implementationName = "com.sun.star.i18n.Transliteration.ignoreZiZu_ja_JP";
}

} } } }
<|endoftext|>


<commit_before>#include <iostream>

extern "C"
{
	#include "lua.h"
	#include "lauxlib.h"
	#include "lualib.h"
}

bool dostring(lua_State* L, const char* str)
{
	if (luaL_loadbuffer(L, str, std::strlen(str), str) || lua_pcall(L, 0, 0, 0))
	{
		const char* a = lua_tostring(L, -1);
		std::cout << a << "\n";
		lua_pop(L, 1);
		return true;
	}
	return false;
}

#include <luabind/luabind.hpp>
#include <boost/any.hpp>

template<class T>
struct convert_any
{
	static void convert(lua_State* L, const boost::any& a)
	{
		typename luabind::detail::default_policy::template generate_converter<T, luabind::detail::cpp_to_lua>::type conv;

		conv.apply(L, *boost::any_cast<T>(&a));
	}
};

std::map<const std::type_info*, void(*)(lua_State*, const boost::any&)> any_converters;

template<class T>
void register_any_converter()
{
	any_converters[&typeid(T)] = convert_any<T>::convert;
}

namespace luabind
{
	namespace converters
	{
		yes_t is_user_defined(by_value<boost::any>);
		yes_t is_user_defined(by_const_reference<boost::any>);

		void convert_cpp_to_lua(lua_State* L, const boost::any& a)
		{
			typedef void(*conv_t)(lua_State* L, const boost::any&);
			conv_t conv = any_converters[&a.type()];
			conv(L, a);
		}
	}
}

boost::any f(bool b)
{
	if (b) return "foobar";
	else return "3.5f";
}

int main()
{
	register_any_converter<int>();
	register_any_converter<float>();
	register_any_converter<const char*>();
	register_any_converter<std::string>();

	lua_State* L = lua_open();
	lua_baselibopen(L);

	using namespace luabind;

	open(L);
	module(L)
	[
		def("f", &f)
	];

	dostring(L, "print( f(true) )");
	dostring(L, "print( f(false) )");
	dostring(L, "function update(p) print(p) end");

	boost::any param = std::string("foo");

	luabind::call_function<void>(L, "update", param);

	lua_close(L);
}

<commit_msg>fixed any_converter example<commit_after>#include <iostream>

extern "C"
{
	#include "lua.h"
	#include "lauxlib.h"
	#include "lualib.h"
}

bool dostring(lua_State* L, const char* str)
{
	if (luaL_loadbuffer(L, str, std::strlen(str), str) || lua_pcall(L, 0, 0, 0))
	{
		const char* a = lua_tostring(L, -1);
		std::cout << a << "\n";
		lua_pop(L, 1);
		return true;
	}
	return false;
}

#include <luabind/luabind.hpp>
#include <luabind/detail/convert_to_lua.hpp>
#include <boost/any.hpp>

template<class T>
struct convert_any
{
	static void convert(lua_State* L, const boost::any& a)
	{
		luabind::detail::convert_to_lua(L, *boost::any_cast<T>(&a));
	}
};

std::map<const std::type_info*, void(*)(lua_State*, const boost::any&)> any_converters;

template<class T>
void register_any_converter()
{
	any_converters[&typeid(T)] = convert_any<T>::convert;
}

namespace luabind
{
	namespace converters
	{
		yes_t is_user_defined(by_value<boost::any>);
		yes_t is_user_defined(by_const_reference<boost::any>);

		void convert_cpp_to_lua(lua_State* L, const boost::any& a)
		{
			typedef void(*conv_t)(lua_State* L, const boost::any&);
			conv_t conv = any_converters[&a.type()];
			conv(L, a);
		}
	}
}

boost::any f(bool b)
{
	if (b) return "foobar";
	else return "3.5f";
}

int main()
{
	register_any_converter<int>();
	register_any_converter<float>();
	register_any_converter<const char*>();
	register_any_converter<std::string>();

	lua_State* L = lua_open();
#if LUA_VERSION_NUM >= 501
	luaL_openlibs(L);
#else
	lua_baselibopen(L);
#endif

	using namespace luabind;

	open(L);
	module(L)
	[
		def("f", &f)
	];

	dostring(L, "print( f(true) )");
	dostring(L, "print( f(false) )");
	dostring(L, "function update(p) print(p) end");

	boost::any param = std::string("foo");

	luabind::call_function<void>(L, "update", param);

	lua_close(L);
}

<|endoftext|>


<commit_before>/*ckwg +5
 * Copyright 2011 by Kitware, Inc. All Rights Reserved. Please refer to
 * KITWARE_LICENSE.TXT for licensing information, or contact General Counsel,
 * Kitware, Inc., 28 Corporate Drive, Clifton Park, NY 12065.
 */

#include "combine_masks_process.h"

#include <processes/helpers/image/format.h>
#include <processes/helpers/image/operators.h>
#include <processes/helpers/image/pixtypes.h>

#include <vistk/pipeline/datum.h>
#include <vistk/pipeline/process_exception.h>

#include <boost/algorithm/string/predicate.hpp>
#include <boost/foreach.hpp>
#include <boost/make_shared.hpp>

#include <numeric>
#include <string>

/**
 * \file combine_masks_process.cxx
 *
 * \brief Implementation of the mask combination process.
 */

namespace vistk
{

class combine_masks_process::priv
{
  public:
    priv();
    ~priv();

    typedef port_t tag_t;
    typedef std::vector<tag_t> tags_t;

    binop_func_t const combine;
    port_type_t const port_type;

    tags_t tags;

    static port_t const port_mask_prefix;
    static port_t const port_mask;
};

process::port_t const combine_masks_process::priv::port_mask_prefix = process::port_t("mask/");
process::port_t const combine_masks_process::priv::port_mask = process::port_t("mask");

combine_masks_process
::combine_masks_process(config_t const& config)
  : process(config)
  , d(new priv)
{
  ensure_inputs_are_valid(false);

  port_flags_t required;

  required.insert(flag_required);

  declare_output_port(priv::port_mask, boost::make_shared<port_info>(
    d->port_type,
    required,
    port_description_t("The combined mask.")));
}

combine_masks_process
::~combine_masks_process()
{
}

void
combine_masks_process
::_init()
{
  if (!d->combine)
  {
    static std::string const reason = "A combine function for the "
                                      "mask pixtype could not be found";

    throw invalid_configuration_exception(name(), reason);
  }

  if (!d->tags.size())
  {
    static std::string const reason = "There must be at least one mask to combine";

    throw invalid_configuration_exception(name(), reason);
  }

  process::_init();
}

void
combine_masks_process
::_step()
{
  std::vector<datum_t> data;

  datum_t dat;

  BOOST_FOREACH (priv::tag_t const& tag, d->tags)
  {
    datum_t const idat = grab_datum_from_port(priv::port_mask_prefix + tag);

    switch (idat->type())
    {
      case datum::data:
        /// \todo Check image sizes.

        data.push_back(dat);
        break;
      case datum::complete:
        mark_process_as_complete();
        break;
      case datum::invalid:
      case datum::error:
      {
        datum::error_t const err_string = datum::error_t("Error on input tag \'" + tag + "\'");

        dat = datum::error_datum(err_string);
        break;
      }
      case datum::empty:
      default:
        break;
    }

    data.push_back(idat);
  }

  if (!dat)
  {
    dat = std::accumulate(data.begin(), data.end(), datum_t(), d->combine);
  }

  push_datum_to_port(priv::port_mask, dat);

  process::_step();
}

process::port_info_t
combine_masks_process
::_input_port_info(port_t const& port)
{
  if (boost::starts_with(port, priv::port_mask_prefix))
  {
    priv::tag_t const tag = port.substr(priv::port_mask_prefix.size());

    priv::tags_t::const_iterator const i = std::find(d->tags.begin(), d->tags.end(), tag);

    if (i == d->tags.end())
    {
      d->tags.push_back(tag);

      port_flags_t required;

      required.insert(flag_required);

      declare_input_port(port, boost::make_shared<port_info>(
        d->port_type,
        required,
        port_description_t("The \'" + tag + "\' mask.")));
    }
  }

  return process::_input_port_info(port);
}

combine_masks_process::priv
::priv()
  : combine(or_for_pixtype(pixtypes::pixtype_byte()))
  , port_type(port_type_for_pixtype(pixtypes::pixtype_byte(), pixfmts::pixfmt_mask()))
{
}

combine_masks_process::priv
::~priv()
{
}

}
<commit_msg>Delay marking as complete<commit_after>/*ckwg +5
 * Copyright 2011 by Kitware, Inc. All Rights Reserved. Please refer to
 * KITWARE_LICENSE.TXT for licensing information, or contact General Counsel,
 * Kitware, Inc., 28 Corporate Drive, Clifton Park, NY 12065.
 */

#include "combine_masks_process.h"

#include <processes/helpers/image/format.h>
#include <processes/helpers/image/operators.h>
#include <processes/helpers/image/pixtypes.h>

#include <vistk/pipeline/datum.h>
#include <vistk/pipeline/process_exception.h>

#include <boost/algorithm/string/predicate.hpp>
#include <boost/foreach.hpp>
#include <boost/make_shared.hpp>

#include <numeric>
#include <string>

/**
 * \file combine_masks_process.cxx
 *
 * \brief Implementation of the mask combination process.
 */

namespace vistk
{

class combine_masks_process::priv
{
  public:
    priv();
    ~priv();

    typedef port_t tag_t;
    typedef std::vector<tag_t> tags_t;

    binop_func_t const combine;
    port_type_t const port_type;

    tags_t tags;

    static port_t const port_mask_prefix;
    static port_t const port_mask;
};

process::port_t const combine_masks_process::priv::port_mask_prefix = process::port_t("mask/");
process::port_t const combine_masks_process::priv::port_mask = process::port_t("mask");

combine_masks_process
::combine_masks_process(config_t const& config)
  : process(config)
  , d(new priv)
{
  ensure_inputs_are_valid(false);

  port_flags_t required;

  required.insert(flag_required);

  declare_output_port(priv::port_mask, boost::make_shared<port_info>(
    d->port_type,
    required,
    port_description_t("The combined mask.")));
}

combine_masks_process
::~combine_masks_process()
{
}

void
combine_masks_process
::_init()
{
  if (!d->combine)
  {
    static std::string const reason = "A combine function for the "
                                      "mask pixtype could not be found";

    throw invalid_configuration_exception(name(), reason);
  }

  if (!d->tags.size())
  {
    static std::string const reason = "There must be at least one mask to combine";

    throw invalid_configuration_exception(name(), reason);
  }

  process::_init();
}

void
combine_masks_process
::_step()
{
  std::vector<datum_t> data;
  bool complete = false;

  datum_t dat;

  BOOST_FOREACH (priv::tag_t const& tag, d->tags)
  {
    datum_t const idat = grab_datum_from_port(priv::port_mask_prefix + tag);

    switch (idat->type())
    {
      case datum::data:
        /// \todo Check image sizes.

        data.push_back(dat);
        break;
      case datum::complete:
        complete = true;
        break;
      case datum::invalid:
      case datum::error:
      {
        datum::error_t const err_string = datum::error_t("Error on input tag \'" + tag + "\'");

        dat = datum::error_datum(err_string);
        break;
      }
      case datum::empty:
      default:
        break;
    }

    data.push_back(idat);
  }

  if (complete)
  {
    mark_process_as_complete();
    dat = datum::complete_datum();
  }

  if (!dat)
  {
    dat = std::accumulate(data.begin(), data.end(), datum_t(), d->combine);
  }

  push_datum_to_port(priv::port_mask, dat);

  process::_step();
}

process::port_info_t
combine_masks_process
::_input_port_info(port_t const& port)
{
  if (boost::starts_with(port, priv::port_mask_prefix))
  {
    priv::tag_t const tag = port.substr(priv::port_mask_prefix.size());

    priv::tags_t::const_iterator const i = std::find(d->tags.begin(), d->tags.end(), tag);

    if (i == d->tags.end())
    {
      d->tags.push_back(tag);

      port_flags_t required;

      required.insert(flag_required);

      declare_input_port(port, boost::make_shared<port_info>(
        d->port_type,
        required,
        port_description_t("The \'" + tag + "\' mask.")));
    }
  }

  return process::_input_port_info(port);
}

combine_masks_process::priv
::priv()
  : combine(or_for_pixtype(pixtypes::pixtype_byte()))
  , port_type(port_type_for_pixtype(pixtypes::pixtype_byte(), pixfmts::pixfmt_mask()))
{
}

combine_masks_process::priv
::~priv()
{
}

}
<|endoftext|>


<commit_before>/*******************************************************************************
* CGoGN: Combinatorial and Geometric modeling with Generic N-dimensional Maps  *
* Copyright (C) 2015, IGG Group, ICube, University of Strasbourg, France       *
*                                                                              *
* This library is free software; you can redistribute it and/or modify it      *
* under the terms of the GNU Lesser General Public License as published by the *
* Free Software Foundation; either version 2.1 of the License, or (at your     *
* option) any later version.                                                   *
*                                                                              *
* This library is distributed in the hope that it will be useful, but WITHOUT  *
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or        *
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License  *
* for more details.                                                            *
*                                                                              *
* You should have received a copy of the GNU Lesser General Public License     *
* along with this library; if not, write to the Free Software Foundation,      *
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301 USA.           *
*                                                                              *
* Web site: http://cgogn.unistra.fr/                                           *
* Contact information: cgogn@unistra.fr                                        *
*                                                                              *
*******************************************************************************/

#define CGOGN_CORE_DLL_EXPORT
#define CGOGN_CORE_UTILS_LOGGER_OUTPUT_CPP_

#include <iostream>
#include <limits>

#include <cgogn/core/utils/logger_output.h>

#include <termcolor.hpp>

namespace cgogn
{

namespace logger
{

void NullOutput::process_entry(const LogEntry&)
{}

ConsoleOutput::ConsoleOutput() : LoggerOutput()
{}

void ConsoleOutput::process_entry(const LogEntry& e)
{
	if (e)
	{
		std::ostream& o = (e.get_level() <= LogLevel::LogLevel_DEPRECATED) ? std::cout : std::cerr;
		internal::add_color(o,e.get_level()) << termcolor::bold;
		o << "[" << internal::loglevel_to_string(e.get_level()) << "]" << termcolor::reset;
		if (!e.get_sender().empty())
		{
			o << '(' << termcolor::magenta << e.get_sender() << termcolor::reset << ')';
		}
		o << ": " << e.get_message_str();
		if (e.get_level() >= LogLevel::LogLevel_DEBUG && !e.get_fileinfo().empty())
		{
			o << " (file " << termcolor::magenta;
			o << e.get_fileinfo() << termcolor::reset << ')';
		}
		o << '.' << std::endl;
	}
}

FileOutput::FileOutput(const std::string& filename) : LoggerOutput()
  ,filename_(filename)
{
	out_.open(filename, std::ios_base::out | std::ios_base::trunc);
}

void FileOutput::process_entry(const LogEntry& e)
{
	if (out_.good())
	{
		out_ << "[" << internal::loglevel_to_string(e.get_level()) << "]";
		if (!e.get_sender().empty())
		{
			out_ << '(' << e.get_sender() << ')';
		}
		out_ << ": " << e.get_message_str();
		if (!e.get_fileinfo().empty())
			out_ << " (file " << e.get_fileinfo() << ')';
		out_ << '.' << std::endl;
	}
}

} // namespace logger
} // namespace cgogn
<commit_msg>removed the "." added automatically by the logger.<commit_after>/*******************************************************************************
* CGoGN: Combinatorial and Geometric modeling with Generic N-dimensional Maps  *
* Copyright (C) 2015, IGG Group, ICube, University of Strasbourg, France       *
*                                                                              *
* This library is free software; you can redistribute it and/or modify it      *
* under the terms of the GNU Lesser General Public License as published by the *
* Free Software Foundation; either version 2.1 of the License, or (at your     *
* option) any later version.                                                   *
*                                                                              *
* This library is distributed in the hope that it will be useful, but WITHOUT  *
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or        *
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License  *
* for more details.                                                            *
*                                                                              *
* You should have received a copy of the GNU Lesser General Public License     *
* along with this library; if not, write to the Free Software Foundation,      *
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301 USA.           *
*                                                                              *
* Web site: http://cgogn.unistra.fr/                                           *
* Contact information: cgogn@unistra.fr                                        *
*                                                                              *
*******************************************************************************/

#define CGOGN_CORE_DLL_EXPORT
#define CGOGN_CORE_UTILS_LOGGER_OUTPUT_CPP_

#include <iostream>
#include <limits>

#include <cgogn/core/utils/logger_output.h>

#include <termcolor.hpp>

namespace cgogn
{

namespace logger
{

void NullOutput::process_entry(const LogEntry&)
{}

ConsoleOutput::ConsoleOutput() : LoggerOutput()
{}

void ConsoleOutput::process_entry(const LogEntry& e)
{
	if (e)
	{
		std::ostream& o = (e.get_level() <= LogLevel::LogLevel_DEPRECATED) ? std::cout : std::cerr;
		internal::add_color(o,e.get_level()) << termcolor::bold;
		o << "[" << internal::loglevel_to_string(e.get_level()) << "]" << termcolor::reset;
		if (!e.get_sender().empty())
		{
			o << '(' << termcolor::magenta << e.get_sender() << termcolor::reset << ')';
		}
		o << ": " << e.get_message_str();
		if (e.get_level() >= LogLevel::LogLevel_DEBUG && !e.get_fileinfo().empty())
		{
			o << " (file " << termcolor::magenta;
			o << e.get_fileinfo() << termcolor::reset << ')';
		}
		o << std::endl;
	}
}

FileOutput::FileOutput(const std::string& filename) : LoggerOutput()
  ,filename_(filename)
{
	out_.open(filename, std::ios_base::out | std::ios_base::trunc);
}

void FileOutput::process_entry(const LogEntry& e)
{
	if (out_.good())
	{
		out_ << "[" << internal::loglevel_to_string(e.get_level()) << "]";
		if (!e.get_sender().empty())
		{
			out_ << '(' << e.get_sender() << ')';
		}
		out_ << ": " << e.get_message_str();
		if (!e.get_fileinfo().empty())
			out_ << " (file " << e.get_fileinfo() << ')';
		out_ << std::endl;
	}
}

} // namespace logger
} // namespace cgogn
<|endoftext|>


<commit_before>/*!
	@file
	@author		Albert Semenov
	@date		09/2008
	@module
*//*
	This file is part of MyGUI.

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

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

	You should have received a copy of the GNU Lesser General Public License
	along with MyGUI.  If not, see <http://www.gnu.org/licenses/>.
*/
#include "MyGUI_Precompiled.h"
#include "MyGUI_ResourceManager.h"
#include "MyGUI_LanguageManager.h"
#include "MyGUI_XmlDocument.h"

namespace MyGUI
{

	const std::string XML_TYPE("Language");

	MYGUI_INSTANCE_IMPLEMENT(LanguageManager);

	void LanguageManager::initialise()
	{
		MYGUI_ASSERT(false == mIsInitialise, INSTANCE_TYPE_NAME << " initialised twice");
		MYGUI_LOG(Info, "* Initialise: " << INSTANCE_TYPE_NAME);

		ResourceManager::getInstance().registerLoadXmlDelegate(XML_TYPE) = newDelegate(this, &LanguageManager::_load);

		mCurrentLanguage = mMapFile.end();

		MYGUI_LOG(Info, INSTANCE_TYPE_NAME << " successfully initialized");
		mIsInitialise = true;
	}

	void LanguageManager::shutdown()
	{
		if (false == mIsInitialise) return;
		MYGUI_LOG(Info, "* Shutdown: " << INSTANCE_TYPE_NAME);

		ResourceManager::getInstance().unregisterLoadXmlDelegate(XML_TYPE);

		MYGUI_LOG(Info, INSTANCE_TYPE_NAME << " successfully shutdown");
		mIsInitialise = false;
	}

	bool LanguageManager::load(const std::string & _file, const std::string & _group)
	{
		return ResourceManager::getInstance()._loadImplement(_file, _group, true, XML_TYPE, INSTANCE_TYPE_NAME);
	}

	void LanguageManager::_load(xml::ElementPtr _node, const std::string & _file, Version _version)
	{
		std::string def;

		// берем детей и крутимся, основной цикл
		xml::ElementEnumerator root = _node->getElementEnumerator();
		while (root.next(XML_TYPE)) {

			// парсим атрибуты
			root->findAttribute("default", def);

			// берем детей и крутимся
			xml::ElementEnumerator info = root->getElementEnumerator();
			while (info.next("Info")) {

				// парсим атрибуты
				std::string name(info->findAttribute("name"));

				// доюавляем в карту пользователя
				if (name.empty()) {
					xml::ElementEnumerator source_info = info->getElementEnumerator();
					while (source_info.next("Source")) {
						loadLanguage(source_info->getContent(), ResourceManager::getInstance().getResourceGroup(), true);
					};

				}
				// добавляем в карту языков
				else {
					MapListString::iterator lang = mMapFile.find(name);
					if (lang == mMapFile.end()) {
						lang = mMapFile.insert(std::make_pair(name, VectorString())).first;
					}

					xml::ElementEnumerator source_info = info->getElementEnumerator();
					while (source_info.next("Source")) {
						lang->second.push_back(source_info->getContent());
					};
				}

			};
		};

		if ( ! def.empty()) setCurrentLanguage(def);
	}

	bool LanguageManager::setCurrentLanguage(const std::string & _name)
	{
		mCurrentLanguage = mMapFile.find(_name);
		if (mCurrentLanguage == mMapFile.end()) {
			MYGUI_LOG(Error, "Language '" << _name << "' is not found");
			return false;
		}

		loadLanguage(mCurrentLanguage->second, ResourceManager::getInstance().getResourceGroup());
		eventChangeLanguage(mCurrentLanguage->first);
		return true;
	}

	void LanguageManager::loadLanguage(const VectorString & _list, const std::string & _group)
	{
		mMapLanguage.clear();

		for (VectorString::const_iterator iter=_list.begin(); iter!=_list.end(); ++iter) {
			loadLanguage(*iter, _group);
		}
	}

	bool LanguageManager::loadLanguage(const std::string & _file, const std::string & _group, bool _user)
	{

		if (!_group.empty()) {

			if (!helper::isFileExist(_file, _group)) {
				MYGUI_LOG(Error, "file '" << _file << "' not found in group'" << _group << "'");
				return false;
			}

			Ogre::DataStreamPtr stream = Ogre::ResourceGroupManager::getSingletonPtr()->openResource(_file, _group);

			// проверяем на сигнатуру utf8
			uint32 sign = 0;
			stream->read((void*)&sign, 3);
			if (sign != 0x00BFBBEF) {
				MYGUI_LOG(Error, "file '" << _file << "' is not UTF8 format");
				return false;
			}

			_loadLanguage(stream, _user);
			return true;
		}

		std::ifstream stream(_file.c_str());
		if (false == stream.is_open()) {
			MYGUI_LOG(Error, "error open file '" << _file << "'");
			return false;
		}

		// проверяем на сигнатуру utf8
		uint32 sign = 0;
		stream.read((char*)&sign, 3);
		if (sign != 0x00BFBBEF) {
			MYGUI_LOG(Error, "file '" << _file << "' is not UTF8 format");
			stream.close();
			return false;
		}

		_loadLanguage(stream, _user);
		stream.close();

		return true;
	}

	void LanguageManager::_loadLanguage(std::ifstream & _stream, bool _user)
	{
		std::string read;
		while (false == _stream.eof()) {
			std::getline(_stream, read);
			if (read.empty()) continue;

			size_t pos = read.find_first_of(" \t");
			if (_user) {
				if (pos == std::string::npos) mUserMapLanguage[read] = "";
				else mUserMapLanguage[read.substr(0, pos)] = read.substr(pos+1, std::string::npos);
			}
			else {
				if (pos == std::string::npos) mMapLanguage[read] = "";
				else mMapLanguage[read.substr(0, pos)] = read.substr(pos+1, std::string::npos);
			}
		};
	}

	void LanguageManager::_loadLanguage(const Ogre::DataStreamPtr& stream, bool _user)
	{
		std::string read;
		while (false == stream->eof()) {
			read = stream->getLine (false);
			if (read.empty()) continue;

			size_t pos = read.find_first_of(" \t");
			if (_user) {
				if (pos == std::string::npos) mUserMapLanguage[read] = "";
				else mUserMapLanguage[read.substr(0, pos)] = read.substr(pos+1, std::string::npos);
			}
			else {
				if (pos == std::string::npos) mMapLanguage[read] = "";
				else mMapLanguage[read.substr(0, pos)] = read.substr(pos+1, std::string::npos);
			}
		};
	}

	Ogre::UTFString LanguageManager::replaceTags(const Ogre::UTFString & _line)
	{
		// вот хз, что быстрее, итераторы или математика указателей,
		// для непонятно какого размера одного символа UTF8
		Ogre::UTFString line(_line);

		if (mMapLanguage.empty() && mUserMapLanguage.empty()) return _line;

		Ogre::UTFString::iterator end = line.end();
		for (Ogre::UTFString::iterator iter=line.begin(); iter!=end; ++iter) {
			if (*iter == '#') {
				++iter;
				if (iter == end) {
					return line;
				}
				else {
					if (*iter != '{') continue;
					Ogre::UTFString::iterator iter2 = iter;
					++iter2;
					while (true) {
						if (iter2 == end) return line;
						if (*iter2 == '}') {

							size_t start = iter - line.begin();
							size_t len = (iter2 - line.begin()) - start - 1;
							const Ogre::UTFString & tag = line.substr(start + 1, len);

							bool find = true;
							MapLanguageString::iterator replace = mMapLanguage.find(tag);
							if (replace == mMapLanguage.end()) {
								replace = mUserMapLanguage.find(tag);
								find = replace != mUserMapLanguage.end();
							}

							if (!find) {
								iter = line.insert(iter, '#') + size_t(len + 2);
								end = line.end();
								break;
							}
							else {
								iter = line.erase(iter - size_t(1), iter2 + size_t(1));
								size_t pos = iter - line.begin();
								line.insert(pos, replace->second);
								iter = line.begin() + pos + replace->second.length();
								end = line.end();
								if (iter == end) return line;
								break;
							}

							iter = iter2;
							break;
						}
						++iter2;
					};
				}
			}
		}

		return line;
	}

	Ogre::UTFString LanguageManager::getTag(const Ogre::UTFString & _tag)
	{
		MapLanguageString::iterator iter = mMapLanguage.find(_tag);
		if (iter == mMapLanguage.end()) {
			iter = mUserMapLanguage.find(_tag);
			if (iter != mUserMapLanguage.end()) return iter->second;
			return _tag;
		}

		return iter->second;
	}

} // namespace MyGUI
<commit_msg>fix LanguageManager<commit_after>/*!
	@file
	@author		Albert Semenov
	@date		09/2008
	@module
*//*
	This file is part of MyGUI.

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

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

	You should have received a copy of the GNU Lesser General Public License
	along with MyGUI.  If not, see <http://www.gnu.org/licenses/>.
*/
#include "MyGUI_Precompiled.h"
#include "MyGUI_ResourceManager.h"
#include "MyGUI_LanguageManager.h"
#include "MyGUI_XmlDocument.h"

namespace MyGUI
{

	const std::string XML_TYPE("Language");

	MYGUI_INSTANCE_IMPLEMENT(LanguageManager);

	void LanguageManager::initialise()
	{
		MYGUI_ASSERT(false == mIsInitialise, INSTANCE_TYPE_NAME << " initialised twice");
		MYGUI_LOG(Info, "* Initialise: " << INSTANCE_TYPE_NAME);

		ResourceManager::getInstance().registerLoadXmlDelegate(XML_TYPE) = newDelegate(this, &LanguageManager::_load);

		mCurrentLanguage = mMapFile.end();

		MYGUI_LOG(Info, INSTANCE_TYPE_NAME << " successfully initialized");
		mIsInitialise = true;
	}

	void LanguageManager::shutdown()
	{
		if (false == mIsInitialise) return;
		MYGUI_LOG(Info, "* Shutdown: " << INSTANCE_TYPE_NAME);

		ResourceManager::getInstance().unregisterLoadXmlDelegate(XML_TYPE);

		MYGUI_LOG(Info, INSTANCE_TYPE_NAME << " successfully shutdown");
		mIsInitialise = false;
	}

	bool LanguageManager::load(const std::string & _file, const std::string & _group)
	{
		return ResourceManager::getInstance()._loadImplement(_file, _group, true, XML_TYPE, INSTANCE_TYPE_NAME);
	}

	void LanguageManager::_load(xml::ElementPtr _node, const std::string & _file, Version _version)
	{
		std::string def;

		// берем детей и крутимся, основной цикл
		xml::ElementEnumerator root = _node->getElementEnumerator();
		while (root.next(XML_TYPE)) {

			// парсим атрибуты
			root->findAttribute("default", def);

			// берем детей и крутимся
			xml::ElementEnumerator info = root->getElementEnumerator();
			while (info.next("Info")) {

				// парсим атрибуты
				std::string name(info->findAttribute("name"));

				// доюавляем в карту пользователя
				if (name.empty()) {
					xml::ElementEnumerator source_info = info->getElementEnumerator();
					while (source_info.next("Source")) {
						loadLanguage(source_info->getContent(), ResourceManager::getInstance().getResourceGroup(), true);
					};

				}
				// добавляем в карту языков
				else {
					MapListString::iterator lang = mMapFile.find(name);
					if (lang == mMapFile.end()) {
						lang = mMapFile.insert(std::make_pair(name, VectorString())).first;
					}

					xml::ElementEnumerator source_info = info->getElementEnumerator();
					while (source_info.next("Source")) {
						lang->second.push_back(source_info->getContent());
					};
				}

			};
		};

		if ( ! def.empty()) setCurrentLanguage(def);
	}

	bool LanguageManager::setCurrentLanguage(const std::string & _name)
	{
		mCurrentLanguage = mMapFile.find(_name);
		if (mCurrentLanguage == mMapFile.end()) {
			MYGUI_LOG(Error, "Language '" << _name << "' is not found");
			return false;
		}

		loadLanguage(mCurrentLanguage->second, ResourceManager::getInstance().getResourceGroup());
		eventChangeLanguage(mCurrentLanguage->first);
		return true;
	}

	void LanguageManager::loadLanguage(const VectorString & _list, const std::string & _group)
	{
		mMapLanguage.clear();

		for (VectorString::const_iterator iter=_list.begin(); iter!=_list.end(); ++iter) {
			loadLanguage(*iter, _group);
		}
	}

	bool LanguageManager::loadLanguage(const std::string & _file, const std::string & _group, bool _user)
	{

		if (!_group.empty()) {

			if (!helper::isFileExist(_file, _group)) {
				MYGUI_LOG(Error, "file '" << _file << "' not found in group'" << _group << "'");
				return false;
			}

			Ogre::DataStreamPtr stream = Ogre::ResourceGroupManager::getSingletonPtr()->openResource(_file, _group);

			// проверяем на сигнатуру utf8
			uint32 sign = 0;
			stream->read((void*)&sign, 3);
			if (sign != 0x00BFBBEF) {
				MYGUI_LOG(Error, "file '" << _file << "' is not UTF8 format");
				return false;
			}

			_loadLanguage(stream, _user);
			return true;
		}

		std::ifstream stream(_file.c_str());
		if (false == stream.is_open()) {
			MYGUI_LOG(Error, "error open file '" << _file << "'");
			return false;
		}

		// проверяем на сигнатуру utf8
		uint32 sign = 0;
		stream.read((char*)&sign, 3);
		if (sign != 0x00BFBBEF) {
			MYGUI_LOG(Error, "file '" << _file << "' is not UTF8 format");
			stream.close();
			return false;
		}

		_loadLanguage(stream, _user);
		stream.close();

		return true;
	}

	void LanguageManager::_loadLanguage(std::ifstream & _stream, bool _user)
	{
		std::string read;
		while (false == _stream.eof()) {
			std::getline(_stream, read);
			if (read.empty()) continue;

			size_t pos = read.find_first_of(" \t");
			if (_user) {
				if (pos == std::string::npos) mUserMapLanguage[read] = "";
				else mUserMapLanguage[read.substr(0, pos)] = read.substr(pos+1, std::string::npos);
			}
			else {
				if (pos == std::string::npos) mMapLanguage[read] = "";
				else mMapLanguage[read.substr(0, pos)] = read.substr(pos+1, std::string::npos);
			}
		};
	}

	void LanguageManager::_loadLanguage(const Ogre::DataStreamPtr& stream, bool _user)
	{
		std::string read;
		while (false == stream->eof()) {
			read = stream->getLine (false);
			if (read.empty()) continue;

			size_t pos = read.find_first_of(" \t");
			if (_user) {
				if (pos == std::string::npos) mUserMapLanguage[read] = "";
				else mUserMapLanguage[read.substr(0, pos)] = read.substr(pos+1, std::string::npos);
			}
			else {
				if (pos == std::string::npos) mMapLanguage[read] = "";
				else mMapLanguage[read.substr(0, pos)] = read.substr(pos+1, std::string::npos);
			}
		};
	}

	Ogre::UTFString LanguageManager::replaceTags(const Ogre::UTFString & _line)
	{
		// вот хз, что быстрее, итераторы или математика указателей,
		// для непонятно какого размера одного символа UTF8
		Ogre::UTFString line(_line);

		if (mMapLanguage.empty() && mUserMapLanguage.empty()) return _line;

		Ogre::UTFString::iterator end = line.end();
		for (Ogre::UTFString::iterator iter=line.begin(); iter!=end; ) {
			if (*iter == '#')
			{
				++iter;
				if (iter == end)
				{
					return line;
				}
				else
				{
					if (*iter != '{')
					{
						++iter;
						continue;
					}
					Ogre::UTFString::iterator iter2 = iter;
					++iter2;
					while (true)
					{
						if (iter2 == end) return line;
						if (*iter2 == '}')
						{
							size_t start = iter - line.begin();
							size_t len = (iter2 - line.begin()) - start - 1;
							const Ogre::UTFString & tag = line.substr(start + 1, len);

							bool find = true;
							MapLanguageString::iterator replace = mMapLanguage.find(tag);
							if (replace == mMapLanguage.end())
							{
								replace = mUserMapLanguage.find(tag);
								find = replace != mUserMapLanguage.end();
							}

							if (!find)
							{
								iter = line.insert(iter, '#') + size_t(len + 2);
								end = line.end();
								break;
							}
							else
							{
								iter = line.erase(iter - size_t(1), iter2 + size_t(1));
								size_t pos = iter - line.begin();
								line.insert(pos, replace->second);
								iter = line.begin() + pos + replace->second.length();
								end = line.end();
								if (iter == end) return line;
								break;
							}

							iter = iter2;
							break;
						}
						++iter2;
					};
				}
			}
			else
			{
				++iter;
			}
		}

		return line;
	}

	Ogre::UTFString LanguageManager::getTag(const Ogre::UTFString & _tag)
	{
		MapLanguageString::iterator iter = mMapLanguage.find(_tag);
		if (iter == mMapLanguage.end()) {
			iter = mUserMapLanguage.find(_tag);
			if (iter != mUserMapLanguage.end()) return iter->second;
			return _tag;
		}

		return iter->second;
	}

} // namespace MyGUI
<|endoftext|>


<commit_before>/**
 * @file sparse_coding_impl.hpp
 * @author Nishant Mehta
 *
 * Implementation of Sparse Coding with Dictionary Learning using l1 (LASSO) or
 * l1+l2 (Elastic Net) regularization.
 */
#ifndef __MLPACK_METHODS_SPARSE_CODING_SPARSE_CODING_IMPL_HPP
#define __MLPACK_METHODS_SPARSE_CODING_SPARSE_CODING_IMPL_HPP

// In case it hasn't already been included.
#include "sparse_coding.hpp"

namespace mlpack {
namespace sparse_coding {

template<typename DictionaryInitializer>
SparseCoding<DictionaryInitializer>::SparseCoding(const arma::mat& data,
                                                  const size_t atoms,
                                                  const double lambda1,
                                                  const double lambda2) :
    atoms(atoms),
    data(data),
    codes(atoms, data.n_cols),
    lambda1(lambda1),
    lambda2(lambda2)
{
  // Initialize the dictionary.
  DictionaryInitializer::Initialize(data, atoms, dictionary);
}

template<typename DictionaryInitializer>
void SparseCoding<DictionaryInitializer>::Encode(const size_t maxIterations,
                                                 const double objTolerance,
                                                 const double newtonTolerance)
{
  Timer::Start("sparse_coding");

  double lastObjVal = DBL_MAX;

  // Take the initial coding step, which has to happen before entering the main
  // optimization loop.
  Log::Info << "Initial Coding Step." << std::endl;

  OptimizeCode();
  arma::uvec adjacencies = find(codes);

  Log::Info << "  Sparsity level: " << 100.0 * ((double) (adjacencies.n_elem))
      / ((double) (atoms * data.n_cols)) << "%." << std::endl;
  Log::Info << "  Objective value: " << Objective() << "." << std::endl;

  for (size_t t = 1; t != maxIterations; ++t)
  {
    // Print current iteration, and maximum number of iterations (if it isn't
    // 0).
    Log::Info << "Iteration " << t;
    if (maxIterations != 0)
      Log::Info << " of " << maxIterations;
    Log::Info << "." << std::endl;

    // First step: optimize the dictionary.
    Log::Info << "Performing dictionary step... " << std::endl;
    OptimizeDictionary(adjacencies, newtonTolerance);
    Log::Info << "  Objective value: " << Objective() << "." << std::endl;

    // Second step: perform the coding.
    Log::Info << "Performing coding step..." << std::endl;
    OptimizeCode();
    // Get the indices of all the nonzero elements in the codes.
    adjacencies = find(codes);
    Log::Info << "  Sparsity level: " << 100.0 * ((double) (adjacencies.n_elem))
        / ((double) (atoms * data.n_cols)) << "%." << std::endl;

    // Find the new objective value and improvement so we can check for
    // convergence.
    double curObjVal = Objective();
    double improvement = lastObjVal - curObjVal;
    Log::Info << "  Objective value: " << curObjVal << " (improvement "
        << std::scientific << improvement << ")." << std::endl;

    // Have we converged?
    if (improvement < objTolerance)
    {
      Log::Info << "Converged within tolerance " << objTolerance << ".\n";
      break;
    }

    lastObjVal = curObjVal;
  }

  Timer::Stop("sparse_coding");
}

template<typename DictionaryInitializer>
void SparseCoding<DictionaryInitializer>::OptimizeCode()
{
  // When using the Cholesky version of LARS, this is correct even if
  // lambda2 > 0.
  arma::mat matGram = trans(dictionary) * dictionary;

  for (size_t i = 0; i < data.n_cols; ++i)
  {
    // Report progress.
    if ((i % 100) == 0)
      Log::Debug << "Optimization at point " << i << "." << std::endl;

    bool useCholesky = true;
    regression::LARS lars(useCholesky, matGram, lambda1, lambda2);

    // Create an alias of the code (using the same memory), and then LARS will
    // place the result directly into that; then we will not need to have an
    // extra copy.
    arma::vec code = codes.unsafe_col(i);
    lars.Regress(dictionary, data.unsafe_col(i), code, false);
  }
}

// Dictionary step for optimization.
template<typename DictionaryInitializer>
double SparseCoding<DictionaryInitializer>::OptimizeDictionary(
    const arma::uvec& adjacencies,
    const double newtonTolerance)
{
  // Count the number of atomic neighbors for each point x^i.
  arma::uvec neighborCounts = arma::zeros<arma::uvec>(data.n_cols, 1);

  if (adjacencies.n_elem > 0)
  {
    // This gets the column index.  Intentional integer division.
    size_t curPointInd = (size_t) (adjacencies(0) / atoms);

    size_t nextColIndex = (curPointInd + 1) * atoms;
    for (size_t l = 1; l < adjacencies.n_elem; ++l)
    {
      // If l no longer refers to an element in this column, advance the column
      // number accordingly.
      if (adjacencies(l) >= nextColIndex)
      {
        curPointInd = (size_t) (adjacencies(l) / atoms);
        nextColIndex = (curPointInd + 1) * atoms;
      }

      ++neighborCounts(curPointInd);
    }
  }

  // Handle the case of inactive atoms (atoms not used in the given coding).
  std::vector<size_t> inactiveAtoms;

  for (size_t j = 0; j < atoms; ++j)
  {
    if (accu(codes.row(j) != 0) == 0)
      inactiveAtoms.push_back(j);
  }

  const size_t nInactiveAtoms = inactiveAtoms.size();
  const size_t nActiveAtoms = atoms - nInactiveAtoms;

  // Efficient construction of Z restricted to active atoms.
  arma::mat matActiveZ;
  if (nInactiveAtoms > 0)
  {
    math::RemoveRows(codes, inactiveAtoms, matActiveZ);
  }

  if (nInactiveAtoms > 0)
  {
    Log::Warn << "There are " << nInactiveAtoms
        << " inactive atoms. They will be re-initialized randomly.\n";
  }

  Log::Debug << "Solving Dual via Newton's Method.\n";

  // Solve using Newton's method in the dual - note that the final dot
  // multiplication with inv(A) seems to be unavoidable. Although more
  // expensive, the code written this way (we use solve()) should be more
  // numerically stable than just using inv(A) for everything.
  arma::vec dualVars = arma::zeros<arma::vec>(nActiveAtoms);

  //vec dualVars = 1e-14 * ones<vec>(nActiveAtoms);

  // Method used by feature sign code - fails miserably here.  Perhaps the
  // MATLAB optimizer fmincon does something clever?
  //vec dualVars = 10.0 * randu(nActiveAtoms, 1);

  //vec dualVars = diagvec(solve(dictionary, data * trans(codes))
  //    - codes * trans(codes));
  //for (size_t i = 0; i < dualVars.n_elem; i++)
  //  if (dualVars(i) < 0)
  //    dualVars(i) = 0;

  bool converged = false;

  // If we have any inactive atoms, we must construct these differently.
  arma::mat codesXT;
  arma::mat codesZT;

  if (inactiveAtoms.empty())
  {
    codesXT = codes * trans(data);
    codesZT = codes * trans(codes);
  }
  else
  {
    codesXT = matActiveZ * trans(data);
    codesZT = matActiveZ * trans(matActiveZ);
  }

  double normGradient;
  double improvement;
  for (size_t t = 1; !converged; ++t)
  {
    arma::mat A = codesZT + diagmat(dualVars);

    arma::mat matAInvZXT = solve(A, codesXT);

    arma::vec gradient = -arma::sum(arma::square(matAInvZXT), 1);
    gradient += 1;

    arma::mat hessian = -(-2 * (matAInvZXT * trans(matAInvZXT)) % inv(A));

    arma::vec searchDirection = -solve(hessian, gradient);
    //printf("%e\n", norm(searchDirection, 2));

    // Armijo line search.
    const double c = 1e-4;
    double alpha = 1.0;
    const double rho = 0.9;
    double sufficientDecrease = c * dot(gradient, searchDirection);

    while (true)
    {
      // Calculate objective.
      double sumDualVars = sum(dualVars);
      double fOld = -(-trace(trans(codesXT) * matAInvZXT) - sumDualVars);
      double fNew = -(-trace(trans(codesXT) * solve(codesZT +
          diagmat(dualVars + alpha * searchDirection), codesXT)) -
          (sumDualVars + alpha * sum(searchDirection)));

      if (fNew <= fOld + alpha * sufficientDecrease)
      {
        searchDirection = alpha * searchDirection;
        improvement = fOld - fNew;
        break;
      }

      alpha *= rho;
    }

    // Take step and print useful information.
    dualVars += searchDirection;
    normGradient = norm(gradient, 2);
    Log::Debug << "Newton Method iteration " << t << ":" << std::endl;
    Log::Debug << "  Gradient norm: " << std::scientific << normGradient
        << "." << std::endl;
    Log::Debug << "  Improvement: " << std::scientific << improvement << ".\n";

    if (improvement < newtonTolerance)
      converged = true;
  }

  if (inactiveAtoms.empty())
  {
    // Directly update dictionary.
    dictionary = trans(solve(codesZT + diagmat(dualVars), codesXT));
  }
  else
  {
    arma::mat activeDictionary = trans(solve(codesZT +
        diagmat(dualVars), codesXT));

    // Update all atoms.
    size_t currentInactiveIndex = 0;
    for (size_t i = 0; i < atoms; ++i)
    {
      if (inactiveAtoms[currentInactiveIndex] == i)
      {
        // This atom is inactive.  Reinitialize it randomly.
        dictionary.col(i) = (data.col(math::RandInt(data.n_cols)) +
                             data.col(math::RandInt(data.n_cols)) +
                             data.col(math::RandInt(data.n_cols)));

        dictionary.col(i) /= norm(dictionary.col(i), 2);

        // Increment inactive index counter.
        ++currentInactiveIndex;
      }
      else
      {
        // Update estimate.
        dictionary.col(i) = activeDictionary.col(i - currentInactiveIndex);
      }
    }
  }
  //printf("final reconstruction error: %e\n", norm(data - dictionary * codes, "fro"));
  return normGradient;
}

// Project each atom of the dictionary back into the unit ball (if necessary).
template<typename DictionaryInitializer>
void SparseCoding<DictionaryInitializer>::ProjectDictionary()
{
  for (size_t j = 0; j < atoms; j++)
  {
    double atomNorm = norm(dictionary.col(j), 2);
    if (atomNorm > 1)
    {
      Log::Info << "Norm of atom " << j << " exceeds 1 (" << std::scientific
          << atomNorm << ").  Shrinking...\n";
      dictionary.col(j) /= atomNorm;
    }
  }
}

// Compute the objective function.
template<typename DictionaryInitializer>
double SparseCoding<DictionaryInitializer>::Objective() const
{
  double l11NormZ = sum(sum(abs(codes)));
  double froNormResidual = norm(data - (dictionary * codes), "fro");

  if (lambda2 > 0)
  {
    double froNormZ = norm(codes, "fro");
    return 0.5 * (std::pow(froNormResidual, 2.0) + (lambda2 *
        std::pow(froNormZ, 2.0))) + (lambda1 * l11NormZ);
  }
  else // It can be simpler.
  {
    return 0.5 * std::pow(froNormResidual, 2.0) + lambda1 * l11NormZ;
  }
}

template<typename DictionaryInitializer>
std::string SparseCoding<DictionaryInitializer>::ToString() const
{
  std::ostringstream convert;
  convert << "Sparse Coding  [" << this << "]" << std::endl;
  convert << "  Data: " << data.n_rows << "x" ;
  convert <<  data.n_cols << std::endl;
  convert << "  Atoms: " << atoms << std::endl;
  convert << "  Lambda 1: " << lambda1 << std::endl;
  convert << "  Lambda 2: " << lambda2 << std::endl;
  return convert.str();
}

}; // namespace sparse_coding
}; // namespace mlpack

#endif
<commit_msg>Be explicit with calls to arma:: functions.  Although gcc accepts this as-is, we don't have a guarantee that all compilers will.<commit_after>/**
 * @file sparse_coding_impl.hpp
 * @author Nishant Mehta
 *
 * Implementation of Sparse Coding with Dictionary Learning using l1 (LASSO) or
 * l1+l2 (Elastic Net) regularization.
 */
#ifndef __MLPACK_METHODS_SPARSE_CODING_SPARSE_CODING_IMPL_HPP
#define __MLPACK_METHODS_SPARSE_CODING_SPARSE_CODING_IMPL_HPP

// In case it hasn't already been included.
#include "sparse_coding.hpp"

namespace mlpack {
namespace sparse_coding {

template<typename DictionaryInitializer>
SparseCoding<DictionaryInitializer>::SparseCoding(const arma::mat& data,
                                                  const size_t atoms,
                                                  const double lambda1,
                                                  const double lambda2) :
    atoms(atoms),
    data(data),
    codes(atoms, data.n_cols),
    lambda1(lambda1),
    lambda2(lambda2)
{
  // Initialize the dictionary.
  DictionaryInitializer::Initialize(data, atoms, dictionary);
}

template<typename DictionaryInitializer>
void SparseCoding<DictionaryInitializer>::Encode(const size_t maxIterations,
                                                 const double objTolerance,
                                                 const double newtonTolerance)
{
  Timer::Start("sparse_coding");

  double lastObjVal = DBL_MAX;

  // Take the initial coding step, which has to happen before entering the main
  // optimization loop.
  Log::Info << "Initial Coding Step." << std::endl;

  OptimizeCode();
  arma::uvec adjacencies = find(codes);

  Log::Info << "  Sparsity level: " << 100.0 * ((double) (adjacencies.n_elem))
      / ((double) (atoms * data.n_cols)) << "%." << std::endl;
  Log::Info << "  Objective value: " << Objective() << "." << std::endl;

  for (size_t t = 1; t != maxIterations; ++t)
  {
    // Print current iteration, and maximum number of iterations (if it isn't
    // 0).
    Log::Info << "Iteration " << t;
    if (maxIterations != 0)
      Log::Info << " of " << maxIterations;
    Log::Info << "." << std::endl;

    // First step: optimize the dictionary.
    Log::Info << "Performing dictionary step... " << std::endl;
    OptimizeDictionary(adjacencies, newtonTolerance);
    Log::Info << "  Objective value: " << Objective() << "." << std::endl;

    // Second step: perform the coding.
    Log::Info << "Performing coding step..." << std::endl;
    OptimizeCode();
    // Get the indices of all the nonzero elements in the codes.
    adjacencies = find(codes);
    Log::Info << "  Sparsity level: " << 100.0 * ((double) (adjacencies.n_elem))
        / ((double) (atoms * data.n_cols)) << "%." << std::endl;

    // Find the new objective value and improvement so we can check for
    // convergence.
    double curObjVal = Objective();
    double improvement = lastObjVal - curObjVal;
    Log::Info << "  Objective value: " << curObjVal << " (improvement "
        << std::scientific << improvement << ")." << std::endl;

    // Have we converged?
    if (improvement < objTolerance)
    {
      Log::Info << "Converged within tolerance " << objTolerance << ".\n";
      break;
    }

    lastObjVal = curObjVal;
  }

  Timer::Stop("sparse_coding");
}

template<typename DictionaryInitializer>
void SparseCoding<DictionaryInitializer>::OptimizeCode()
{
  // When using the Cholesky version of LARS, this is correct even if
  // lambda2 > 0.
  arma::mat matGram = trans(dictionary) * dictionary;

  for (size_t i = 0; i < data.n_cols; ++i)
  {
    // Report progress.
    if ((i % 100) == 0)
      Log::Debug << "Optimization at point " << i << "." << std::endl;

    bool useCholesky = true;
    regression::LARS lars(useCholesky, matGram, lambda1, lambda2);

    // Create an alias of the code (using the same memory), and then LARS will
    // place the result directly into that; then we will not need to have an
    // extra copy.
    arma::vec code = codes.unsafe_col(i);
    lars.Regress(dictionary, data.unsafe_col(i), code, false);
  }
}

// Dictionary step for optimization.
template<typename DictionaryInitializer>
double SparseCoding<DictionaryInitializer>::OptimizeDictionary(
    const arma::uvec& adjacencies,
    const double newtonTolerance)
{
  // Count the number of atomic neighbors for each point x^i.
  arma::uvec neighborCounts = arma::zeros<arma::uvec>(data.n_cols, 1);

  if (adjacencies.n_elem > 0)
  {
    // This gets the column index.  Intentional integer division.
    size_t curPointInd = (size_t) (adjacencies(0) / atoms);

    size_t nextColIndex = (curPointInd + 1) * atoms;
    for (size_t l = 1; l < adjacencies.n_elem; ++l)
    {
      // If l no longer refers to an element in this column, advance the column
      // number accordingly.
      if (adjacencies(l) >= nextColIndex)
      {
        curPointInd = (size_t) (adjacencies(l) / atoms);
        nextColIndex = (curPointInd + 1) * atoms;
      }

      ++neighborCounts(curPointInd);
    }
  }

  // Handle the case of inactive atoms (atoms not used in the given coding).
  std::vector<size_t> inactiveAtoms;

  for (size_t j = 0; j < atoms; ++j)
  {
    if (arma::accu(codes.row(j) != 0) == 0)
      inactiveAtoms.push_back(j);
  }

  const size_t nInactiveAtoms = inactiveAtoms.size();
  const size_t nActiveAtoms = atoms - nInactiveAtoms;

  // Efficient construction of Z restricted to active atoms.
  arma::mat matActiveZ;
  if (nInactiveAtoms > 0)
  {
    math::RemoveRows(codes, inactiveAtoms, matActiveZ);
  }

  if (nInactiveAtoms > 0)
  {
    Log::Warn << "There are " << nInactiveAtoms
        << " inactive atoms. They will be re-initialized randomly.\n";
  }

  Log::Debug << "Solving Dual via Newton's Method.\n";

  // Solve using Newton's method in the dual - note that the final dot
  // multiplication with inv(A) seems to be unavoidable. Although more
  // expensive, the code written this way (we use solve()) should be more
  // numerically stable than just using inv(A) for everything.
  arma::vec dualVars = arma::zeros<arma::vec>(nActiveAtoms);

  //vec dualVars = 1e-14 * ones<vec>(nActiveAtoms);

  // Method used by feature sign code - fails miserably here.  Perhaps the
  // MATLAB optimizer fmincon does something clever?
  //vec dualVars = 10.0 * randu(nActiveAtoms, 1);

  //vec dualVars = diagvec(solve(dictionary, data * trans(codes))
  //    - codes * trans(codes));
  //for (size_t i = 0; i < dualVars.n_elem; i++)
  //  if (dualVars(i) < 0)
  //    dualVars(i) = 0;

  bool converged = false;

  // If we have any inactive atoms, we must construct these differently.
  arma::mat codesXT;
  arma::mat codesZT;

  if (inactiveAtoms.empty())
  {
    codesXT = codes * trans(data);
    codesZT = codes * trans(codes);
  }
  else
  {
    codesXT = matActiveZ * trans(data);
    codesZT = matActiveZ * trans(matActiveZ);
  }

  double normGradient;
  double improvement;
  for (size_t t = 1; !converged; ++t)
  {
    arma::mat A = codesZT + diagmat(dualVars);

    arma::mat matAInvZXT = solve(A, codesXT);

    arma::vec gradient = -arma::sum(arma::square(matAInvZXT), 1);
    gradient += 1;

    arma::mat hessian = -(-2 * (matAInvZXT * trans(matAInvZXT)) % inv(A));

    arma::vec searchDirection = -solve(hessian, gradient);
    //printf("%e\n", norm(searchDirection, 2));

    // Armijo line search.
    const double c = 1e-4;
    double alpha = 1.0;
    const double rho = 0.9;
    double sufficientDecrease = c * dot(gradient, searchDirection);

    while (true)
    {
      // Calculate objective.
      double sumDualVars = arma::sum(dualVars);
      double fOld = -(-trace(trans(codesXT) * matAInvZXT) - sumDualVars);
      double fNew = -(-trace(trans(codesXT) * solve(codesZT +
          diagmat(dualVars + alpha * searchDirection), codesXT)) -
          (sumDualVars + alpha * arma::sum(searchDirection)));

      if (fNew <= fOld + alpha * sufficientDecrease)
      {
        searchDirection = alpha * searchDirection;
        improvement = fOld - fNew;
        break;
      }

      alpha *= rho;
    }

    // Take step and print useful information.
    dualVars += searchDirection;
    normGradient = arma::norm(gradient, 2);
    Log::Debug << "Newton Method iteration " << t << ":" << std::endl;
    Log::Debug << "  Gradient norm: " << std::scientific << normGradient
        << "." << std::endl;
    Log::Debug << "  Improvement: " << std::scientific << improvement << ".\n";

    if (improvement < newtonTolerance)
      converged = true;
  }

  if (inactiveAtoms.empty())
  {
    // Directly update dictionary.
    dictionary = trans(solve(codesZT + diagmat(dualVars), codesXT));
  }
  else
  {
    arma::mat activeDictionary = trans(solve(codesZT +
        diagmat(dualVars), codesXT));

    // Update all atoms.
    size_t currentInactiveIndex = 0;
    for (size_t i = 0; i < atoms; ++i)
    {
      if (inactiveAtoms[currentInactiveIndex] == i)
      {
        // This atom is inactive.  Reinitialize it randomly.
        dictionary.col(i) = (data.col(math::RandInt(data.n_cols)) +
                             data.col(math::RandInt(data.n_cols)) +
                             data.col(math::RandInt(data.n_cols)));

        dictionary.col(i) /= arma::norm(dictionary.col(i), 2);

        // Increment inactive index counter.
        ++currentInactiveIndex;
      }
      else
      {
        // Update estimate.
        dictionary.col(i) = activeDictionary.col(i - currentInactiveIndex);
      }
    }
  }
  //printf("final reconstruction error: %e\n", norm(data - dictionary * codes, "fro"));
  return normGradient;
}

// Project each atom of the dictionary back into the unit ball (if necessary).
template<typename DictionaryInitializer>
void SparseCoding<DictionaryInitializer>::ProjectDictionary()
{
  for (size_t j = 0; j < atoms; j++)
  {
    double atomNorm = arma::norm(dictionary.col(j), 2);
    if (atomNorm > 1)
    {
      Log::Info << "Norm of atom " << j << " exceeds 1 (" << std::scientific
          << atomNorm << ").  Shrinking...\n";
      dictionary.col(j) /= atomNorm;
    }
  }
}

// Compute the objective function.
template<typename DictionaryInitializer>
double SparseCoding<DictionaryInitializer>::Objective() const
{
  double l11NormZ = arma::sum(arma::sum(arma::abs(codes)));
  double froNormResidual = arma::norm(data - (dictionary * codes), "fro");

  if (lambda2 > 0)
  {
    double froNormZ = arma::norm(codes, "fro");
    return 0.5 * (std::pow(froNormResidual, 2.0) + (lambda2 *
        std::pow(froNormZ, 2.0))) + (lambda1 * l11NormZ);
  }
  else // It can be simpler.
  {
    return 0.5 * std::pow(froNormResidual, 2.0) + lambda1 * l11NormZ;
  }
}

template<typename DictionaryInitializer>
std::string SparseCoding<DictionaryInitializer>::ToString() const
{
  std::ostringstream convert;
  convert << "Sparse Coding  [" << this << "]" << std::endl;
  convert << "  Data: " << data.n_rows << "x" ;
  convert <<  data.n_cols << std::endl;
  convert << "  Atoms: " << atoms << std::endl;
  convert << "  Lambda 1: " << lambda1 << std::endl;
  convert << "  Lambda 2: " << lambda2 << std::endl;
  return convert.str();
}

}; // namespace sparse_coding
}; // namespace mlpack

#endif
<|endoftext|>


<commit_before>#pragma once

#include "generator/feature_merger.hpp"
#include "generator/generate_info.hpp"

#include "indexer/scales.hpp"

#include "base/logging.hpp"

#include "defines.hpp"

/// Process FeatureBuilder1 for world map. Main functions:
/// - check for visibility in world map
/// - merge linear features
template <class FeatureOutT>
class WorldMapGenerator
{
  class EmitterImpl : public FeatureEmitterIFace
  {
    FeatureOutT m_output;

  public:
    explicit EmitterImpl(feature::GenerateInfo const & info)
      : m_output(info.GetTmpFileName(WORLD_FILE_NAME))
    {
      LOG(LINFO, ("Output World file:", info.GetTmpFileName(WORLD_FILE_NAME)));
    }

    /// This function is called after merging linear features.
    virtual void operator() (FeatureBuilder1 const & fb)
    {
      // do additional check for suitable size of feature
      if (NeedPushToWorld(fb) && scales::IsGoodForLevel(scales::GetUpperWorldScale(), fb.GetLimitRect()))
        PushSure(fb);
    }

    bool NeedPushToWorld(FeatureBuilder1 const & fb) const
    {
      // GetMinFeatureDrawScale also checks suitable size for AREA features
      return (scales::GetUpperWorldScale() >= fb.GetMinFeatureDrawScale());
    }

    void PushSure(FeatureBuilder1 const & fb) { m_output(fb); }
  };

  EmitterImpl m_worldBucket;
  FeatureTypesProcessor m_typesCorrector;
  FeatureMergeProcessor m_merger;

public:
  template <class TInfo>
  explicit WorldMapGenerator(TInfo const & info)
    : m_worldBucket(info),
      m_merger(POINT_COORD_BITS - (scales::GetUpperScale() - scales::GetUpperWorldScale()) / 2)
  {
    // Do not strip last types for given tags,
    // for example, do not cut 'admin_level' in  'boundary-administrative-XXX'.
    char const * arr1[][3] = {
      { "boundary", "administrative", "2" },
      { "boundary", "administrative", "3" },
      { "boundary", "administrative", "4" }
    };

    for (size_t i = 0; i < ARRAY_SIZE(arr1); ++i)
      m_typesCorrector.SetDontNormalizeType(arr1[i]);

    char const * arr2[]  = { "boundary", "administrative", "4", "state" };
    m_typesCorrector.SetDontNormalizeType(arr2);

    /// @todo It's not obvious to integrate link->way conversion.
    /// Review it in future.
    /*
    char const * arr3[][2]  = {
      { "highway", "motorway_link" },
      { "highway", "primary_link" },
      { "highway", "secondary_link" },
      { "highway", "trunk_link" }
    };
    char const * arr4[][2]  = {
      { "highway", "motorway" },
      { "highway", "primary" },
      { "highway", "secondary" },
      { "highway", "trunk" }
    };
    STATIS_ASSERT(ARRAY_SIZE(arr3) == ARRAY_SIZE(arr4));

    for (size_t i = 0; i < ARRAY_SIZE(arr3); ++i)
      m_typesCorrector.SetMappingTypes(arr3[i], arr4[i]);
    */
  }

  void operator()(FeatureBuilder1 fb)
  {
    if (m_worldBucket.NeedPushToWorld(fb))
    {
      if (fb.GetGeomType() == feature::GEOM_LINE)
      {
        MergedFeatureBuilder1 * p = m_typesCorrector(fb);
        if (p)
          m_merger(p);
      }
      else
      {
        if (feature::PreprocessForWorldMap(fb))
          m_worldBucket.PushSure(fb);
      }
    }
  }

  void DoMerge()
  {
    m_merger.DoMerge(m_worldBucket);
  }
};

template <class FeatureOutT>
class CountryMapGenerator
{
  FeatureOutT m_bucket;

public:
  template <class TInfo>
  explicit CountryMapGenerator(TInfo const & info) : m_bucket(info) {}

  void operator()(FeatureBuilder1 fb)
  {
    if (feature::PreprocessForCountryMap(fb))
      m_bucket(fb);
  }

  FeatureOutT const & Parent() const { return m_bucket; }
};
<commit_msg>Check borders<commit_after>#pragma once

#include "generator/feature_merger.hpp"
#include "generator/generate_info.hpp"

#include "indexer/scales.hpp"

#include "base/logging.hpp"

#include "defines.hpp"

/// Process FeatureBuilder1 for world map. Main functions:
/// - check for visibility in world map
/// - merge linear features
template <class FeatureOutT>
class WorldMapGenerator
{
  class EmitterImpl : public FeatureEmitterIFace
  {
    FeatureOutT m_output;
    uint32_t m_boundaryType;
    list<m2::RegionD> m_waterRegions;

  public:
    explicit EmitterImpl(feature::GenerateInfo const & info)
      : m_output(info.GetTmpFileName(WORLD_FILE_NAME))
    {
      m_boundaryType = classif().GetTypeByPath({ "boundary", "administrative"});
      LoadWatersRegionsDump(info.m_intermediateDir + WORLD_COASTS_FILE_NAME + ".rawdump");
      LOG(LINFO, ("Output World file:", info.GetTmpFileName(WORLD_FILE_NAME)));
    }

    void LoadWatersRegionsDump(string const &dumpFileName)
    {
      LOG(LINFO, ("Load water polygons:", dumpFileName));
      ifstream file;
      file.exceptions(ifstream::badbit);
      file.open(dumpFileName);
      if (!file.is_open())
        LOG(LCRITICAL, ("Can't open water polygons"));

      size_t total = 0;
      while (true)
      {
        uint64_t numGeometries = 0;
        file.read(reinterpret_cast<char *>(&numGeometries), sizeof(numGeometries));

        if (numGeometries == 0)
          break;

        ++total;

        vector<m2::PointD> points;
        for (size_t i = 0; i < numGeometries; ++i)
        {
          uint64_t numPoints = 0;
          file.read(reinterpret_cast<char *>(&numPoints), sizeof(numPoints));
          points.resize(numPoints);
          file.read(reinterpret_cast<char *>(points.data()), sizeof(m2::PointD) * numPoints);
          m_waterRegions.push_back(m2::RegionD());
          m_waterRegions.back().Assign(points.begin(), points.end());
        }
      }

      LOG(LINFO, ("Load", total, "water polygons"));
    }

    /// This function is called after merging linear features.
    virtual void operator() (FeatureBuilder1 const & fb)
    {
      // do additional check for suitable size of feature
      if (NeedPushToWorld(fb) && scales::IsGoodForLevel(scales::GetUpperWorldScale(), fb.GetLimitRect()))
        PushSure(fb);
    }

    bool IsWaterBoundaries(FeatureBuilder1 const & fb) const
    {
      if (fb.FindType(m_boundaryType, 2) == ftype::GetEmptyValue())
        return false;

      m2::PointD pts[3] = {{0, 0}, {0, 0}, {0, 0}};
      size_t hits[3] = {0, 0, 0};

      pts[0] = fb.GetGeometry().front().front();
      pts[1] = *(fb.GetGeometry().front().begin() + fb.GetGeometry().front().size()/2);
      pts[2] = fb.GetGeometry().front().back();

      for (m2::RegionD const & region : m_waterRegions)
      {
        hits[0] += region.Contains(pts[0]) ? 1 : 0;
        hits[1] += region.Contains(pts[1]) ? 1 : 0;
        hits[2] += region.Contains(pts[2]) ? 1 : 0;
      }

      size_t state = (hits[0] & 0x01) + (hits[1] & 0x01) + (hits[2] & 0x01);

      LOG(LINFO, ("hits:", hits, "Boundary state:", state, "Dump:", DebugPrint(fb)));

      // whole border on land
      if (state == 0)
        return false;

      // whole border on water
      if (state == 3)
        return true;

      LOG(LINFO, ("Found partial boundary"));
      return false;
    }

    bool NeedPushToWorld(FeatureBuilder1 const & fb) const
    {
      if (IsWaterBoundaries(fb))
      {
        LOG(LINFO, ("Skip boundary"));
        return false;
      }
      // GetMinFeatureDrawScale also checks suitable size for AREA features
      return (scales::GetUpperWorldScale() >= fb.GetMinFeatureDrawScale());
    }

    void PushSure(FeatureBuilder1 const & fb) { m_output(fb); }
  };

  EmitterImpl m_worldBucket;
  FeatureTypesProcessor m_typesCorrector;
  FeatureMergeProcessor m_merger;

public:
  template <class TInfo>
  explicit WorldMapGenerator(TInfo const & info)
    : m_worldBucket(info),
      m_merger(POINT_COORD_BITS - (scales::GetUpperScale() - scales::GetUpperWorldScale()) / 2)
  {
    // Do not strip last types for given tags,
    // for example, do not cut 'admin_level' in  'boundary-administrative-XXX'.
    char const * arr1[][3] = {
      { "boundary", "administrative", "2" },
      { "boundary", "administrative", "3" },
      { "boundary", "administrative", "4" }
    };

    for (size_t i = 0; i < ARRAY_SIZE(arr1); ++i)
      m_typesCorrector.SetDontNormalizeType(arr1[i]);

    char const * arr2[]  = { "boundary", "administrative", "4", "state" };
    m_typesCorrector.SetDontNormalizeType(arr2);

    /// @todo It's not obvious to integrate link->way conversion.
    /// Review it in future.
    /*
    char const * arr3[][2]  = {
      { "highway", "motorway_link" },
      { "highway", "primary_link" },
      { "highway", "secondary_link" },
      { "highway", "trunk_link" }
    };
    char const * arr4[][2]  = {
      { "highway", "motorway" },
      { "highway", "primary" },
      { "highway", "secondary" },
      { "highway", "trunk" }
    };
    STATIS_ASSERT(ARRAY_SIZE(arr3) == ARRAY_SIZE(arr4));

    for (size_t i = 0; i < ARRAY_SIZE(arr3); ++i)
      m_typesCorrector.SetMappingTypes(arr3[i], arr4[i]);
    */
  }

  void operator()(FeatureBuilder1 fb)
  {
    if (m_worldBucket.NeedPushToWorld(fb))
    {
      if (fb.GetGeomType() == feature::GEOM_LINE)
      {
        MergedFeatureBuilder1 * p = m_typesCorrector(fb);
        if (p)
          m_merger(p);
      }
      else
      {
        if (feature::PreprocessForWorldMap(fb))
          m_worldBucket.PushSure(fb);
      }
    }
  }

  void DoMerge()
  {
    m_merger.DoMerge(m_worldBucket);
  }
};

template <class FeatureOutT>
class CountryMapGenerator
{
  FeatureOutT m_bucket;

public:
  template <class TInfo>
  explicit CountryMapGenerator(TInfo const & info) : m_bucket(info) {}

  void operator()(FeatureBuilder1 fb)
  {
    if (feature::PreprocessForCountryMap(fb))
      m_bucket(fb);
  }

  FeatureOutT const & Parent() const { return m_bucket; }
};
<|endoftext|>