<commit_before>// Copyright (c) 2009 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include <string>

#include "app/l10n_util.h"
#include "base/sys_info.h"
#include "chrome/app/chrome_dll_resource.h"
#include "chrome/browser/app_modal_dialog.h"
#include "chrome/browser/browser.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/renderer_host/render_process_host.h"
#include "chrome/browser/tab_contents/tab_contents.h"
#include "chrome/common/url_constants.h"
#include "chrome/common/page_transition_types.h"
#include "chrome/test/in_process_browser_test.h"
#include "chrome/test/ui_test_utils.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "grit/chromium_strings.h"
#include "grit/generated_resources.h"

const std::string BEFORE_UNLOAD_HTML =
    "<title>beforeunload</title>"
    ""
    "";

const std::wstring OPEN_NEW_BEFOREUNLOAD_PAGE =
    L"w=window.open(); w.onbeforeunload=function(e){return 'foo'};";

namespace {

// Given a page title, returns the expected window caption string.
std::wstring WindowCaptionFromPageTitle(std::wstring page_title) {
#if defined(OS_MACOSX) || defined(OS_CHROMEOS)
  // On Mac or ChromeOS, we don't want to suffix the page title with
  // the application name.
  if (page_title.empty())
    return l10n_util::GetString(IDS_BROWSER_WINDOW_MAC_TAB_UNTITLED);
  return page_title;
#elif defined(OS_WIN) || defined(OS_LINUX)
  if (page_title.empty())
    return l10n_util::GetString(IDS_PRODUCT_NAME);

  return l10n_util::GetStringF(IDS_BROWSER_WINDOW_TITLE_FORMAT, page_title);
#endif
}

// Returns the number of active RenderProcessHosts.
int CountRenderProcessHosts() {
  int result = 0;
  for (RenderProcessHost::iterator i(RenderProcessHost::AllHostsIterator());
       !i.IsAtEnd(); i.Advance())
    ++result;
  return result;
}

}  // namespace

class BrowserTest : public InProcessBrowserTest {
 protected:
  // In RTL locales wrap the page title with RTL embedding characters so that it
  // matches the value returned by GetWindowTitle().
  std::wstring LocaleWindowCaptionFromPageTitle(
      const std::wstring& expected_title) {
    std::wstring page_title = WindowCaptionFromPageTitle(expected_title);
#if defined(OS_WIN)
    std::string locale = g_browser_process->GetApplicationLocale();
    if (l10n_util::GetTextDirectionForLocale(locale.c_str()) ==
        l10n_util::RIGHT_TO_LEFT) {
      l10n_util::WrapStringWithLTRFormatting(&page_title);
    }

    return page_title;
#else
    // Do we need to use the above code on POSIX as well?
    return page_title;
#endif
  }
};

// Launch the app on a page with no title, check that the app title was set
// correctly.
IN_PROC_BROWSER_TEST_F(BrowserTest, NoTitle) {
  ui_test_utils::NavigateToURL(browser(),
                               ui_test_utils::GetTestUrl(L".", L"title1.html"));
  EXPECT_EQ(LocaleWindowCaptionFromPageTitle(L"title1.html"),
            UTF16ToWideHack(browser()->GetWindowTitleForCurrentTab()));
  string16 tab_title;
  ASSERT_TRUE(ui_test_utils::GetCurrentTabTitle(browser(), &tab_title));
  EXPECT_EQ(ASCIIToUTF16("title1.html"), tab_title);
}

// Launch the app, navigate to a page with a title, check that the app title
// was set correctly.
IN_PROC_BROWSER_TEST_F(BrowserTest, Title) {
  ui_test_utils::NavigateToURL(browser(),
                               ui_test_utils::GetTestUrl(L".", L"title2.html"));
  const std::wstring test_title(L"Title Of Awesomeness");
  EXPECT_EQ(LocaleWindowCaptionFromPageTitle(test_title),
            UTF16ToWideHack(browser()->GetWindowTitleForCurrentTab()));
  string16 tab_title;
  ASSERT_TRUE(ui_test_utils::GetCurrentTabTitle(browser(), &tab_title));
  EXPECT_EQ(WideToUTF16(test_title), tab_title);
}

#if !defined(OS_MACOSX)
// TODO(port): BUG16322
IN_PROC_BROWSER_TEST_F(BrowserTest, JavascriptAlertActivatesTab) {
  GURL url(ui_test_utils::GetTestUrl(L".", L"title1.html"));
  ui_test_utils::NavigateToURL(browser(), url);
  browser()->AddTabWithURL(url, GURL(), PageTransition::TYPED,
                           true, 0, false, NULL);
  EXPECT_EQ(2, browser()->tab_count());
  EXPECT_EQ(0, browser()->selected_index());
  TabContents* second_tab = browser()->GetTabContentsAt(1);
  ASSERT_TRUE(second_tab);
  second_tab->render_view_host()->ExecuteJavascriptInWebFrame(L"",
      L"alert('Activate!');");
  AppModalDialog* alert = ui_test_utils::WaitForAppModalDialog();
  alert->CloseModalDialog();
  EXPECT_EQ(2, browser()->tab_count());
  EXPECT_EQ(1, browser()->selected_index());
}
#endif  // !defined(OS_MACOSX)

// Create 34 tabs and verify that a lot of processes have been created. The
// exact number of processes depends on the amount of memory. Previously we
// had a hard limit of 31 processes and this test is mainly directed at
// verifying that we don't crash when we pass this limit.
IN_PROC_BROWSER_TEST_F(BrowserTest, ThirtyFourTabs) {
  GURL url(ui_test_utils::GetTestUrl(L".", L"title2.html"));

  // There is one initial tab.
  for (int ix = 0; ix != 33; ++ix) {
    browser()->AddTabWithURL(url, GURL(), PageTransition::TYPED,
                             true, 0, false, NULL);
  }
  EXPECT_EQ(34, browser()->tab_count());

  // See browser\renderer_host\render_process_host.cc for the algorithm to
  // decide how many processes to create.
  if (base::SysInfo::AmountOfPhysicalMemoryMB() >= 2048) {
    EXPECT_GE(CountRenderProcessHosts(), 24);
  } else {
    EXPECT_LE(CountRenderProcessHosts(), 23);
  }
}

// Test for crbug.com/22004.  Reloading a page with a before unload handler and
// then canceling the dialog should not leave the throbber spinning.
#if defined(OS_MACOSX)
IN_PROC_BROWSER_TEST_F(BrowserTest, DISABLED_ReloadThenCancelBeforeUnload) {
#else
IN_PROC_BROWSER_TEST_F(BrowserTest, ReloadThenCancelBeforeUnload) {
#endif
  GURL url("data:text/html," + BEFORE_UNLOAD_HTML);
  ui_test_utils::NavigateToURL(browser(), url);

  // Navigate to another page, but click cancel in the dialog.  Make sure that
  // the throbber stops spinning.
  browser()->Reload();
  AppModalDialog* alert = ui_test_utils::WaitForAppModalDialog();
  alert->CloseModalDialog();
  EXPECT_FALSE(browser()->GetSelectedTabContents()->is_loading());

  // Clear the beforeunload handler so the test can easily exit.
  browser()->GetSelectedTabContents()->render_view_host()->
      ExecuteJavascriptInWebFrame(L"", L"onbeforeunload=null;");
}

// Test for crbug.com/11647.  A page closed with window.close() should not have
// two beforeunload dialogs shown.
#if defined(OS_MACOSX)
IN_PROC_BROWSER_TEST_F(BrowserTest,
                       DISABLED_SingleBeforeUnloadAfterWindowClose) {
#else
IN_PROC_BROWSER_TEST_F(BrowserTest, FLAKY_SingleBeforeUnloadAfterWindowClose) {
#endif
  browser()->GetSelectedTabContents()->render_view_host()->
      ExecuteJavascriptInWebFrame(L"", OPEN_NEW_BEFOREUNLOAD_PAGE);

  // Close the new window with JavaScript, which should show a single
  // beforeunload dialog.  Then show another alert, to make it easy to verify
  // that a second beforeunload dialog isn't shown.
  browser()->GetTabContentsAt(0)->render_view_host()->
      ExecuteJavascriptInWebFrame(L"", L"w.close(); alert('bar');");
  AppModalDialog* alert = ui_test_utils::WaitForAppModalDialog();
  alert->AcceptWindow();

  alert = ui_test_utils::WaitForAppModalDialog();
  EXPECT_FALSE(alert->is_before_unload_dialog());
  alert->AcceptWindow();
}

// Test that get_process_idle_time() returns reasonable values when compared
// with time deltas measured locally.
IN_PROC_BROWSER_TEST_F(BrowserTest, RenderIdleTime) {
  base::TimeTicks start = base::TimeTicks::Now();
  ui_test_utils::NavigateToURL(browser(),
                               ui_test_utils::GetTestUrl(L".", L"title1.html"));
  RenderProcessHost::iterator it(RenderProcessHost::AllHostsIterator());
  for (; !it.IsAtEnd(); it.Advance()) {
    base::TimeDelta renderer_td =
        it.GetCurrentValue()->get_child_process_idle_time();
    base::TimeDelta browser_td = base::TimeTicks::Now() - start;
    EXPECT_TRUE(browser_td >= renderer_td);
  }
}

// Test IDC_CREATE_SHORTCUTS command is enabled for url scheme file, ftp, http
// and https and disabled for chrome://, about:// etc.
#if defined(OS_MACOSX)
IN_PROC_BROWSER_TEST_F(BrowserTest,
                       DISABLED_CommandCreateAppShortcut) {
#else
IN_PROC_BROWSER_TEST_F(BrowserTest, CommandCreateAppShortcut) {
#endif
  static const wchar_t kDocRoot[] = L"chrome/test/data";

  CommandUpdater* command_updater = browser()->command_updater();

  // Urls that are okay to have shortcuts.
  GURL file_url(ui_test_utils::GetTestUrl(L".", L"empty.html"));
  ASSERT_TRUE(file_url.SchemeIs(chrome::kFileScheme));
  ui_test_utils::NavigateToURL(browser(), file_url);
  EXPECT_TRUE(command_updater->IsCommandEnabled(IDC_CREATE_SHORTCUTS));

  scoped_refptr<FTPTestServer> ftp_server(
        FTPTestServer::CreateServer(kDocRoot));
  ASSERT_TRUE(NULL != ftp_server.get());
  GURL ftp_url(ftp_server->TestServerPage(""));
  ASSERT_TRUE(ftp_url.SchemeIs(chrome::kFtpScheme));
  ui_test_utils::NavigateToURL(browser(), ftp_url);
  EXPECT_TRUE(command_updater->IsCommandEnabled(IDC_CREATE_SHORTCUTS));

  scoped_refptr<HTTPTestServer> http_server(
        HTTPTestServer::CreateServer(kDocRoot, NULL));
  ASSERT_TRUE(NULL != http_server.get());
  GURL http_url(http_server->TestServerPage(""));
  ASSERT_TRUE(http_url.SchemeIs(chrome::kHttpScheme));
  ui_test_utils::NavigateToURL(browser(), http_url);
  EXPECT_TRUE(command_updater->IsCommandEnabled(IDC_CREATE_SHORTCUTS));

  scoped_refptr<HTTPSTestServer> https_server(
        HTTPSTestServer::CreateGoodServer(kDocRoot));
  ASSERT_TRUE(NULL != https_server.get());
  GURL https_url(https_server->TestServerPage("/"));
  ASSERT_TRUE(https_url.SchemeIs(chrome::kHttpsScheme));
  ui_test_utils::NavigateToURL(browser(), https_url);
  EXPECT_TRUE(command_updater->IsCommandEnabled(IDC_CREATE_SHORTCUTS));

  // Urls that should not have shortcuts.
  GURL new_tab_url(chrome::kChromeUINewTabURL);
  ui_test_utils::NavigateToURL(browser(), new_tab_url);
  EXPECT_FALSE(command_updater->IsCommandEnabled(IDC_CREATE_SHORTCUTS));

  GURL history_url(chrome::kChromeUIHistoryURL);
  ui_test_utils::NavigateToURL(browser(), history_url);
  EXPECT_FALSE(command_updater->IsCommandEnabled(IDC_CREATE_SHORTCUTS));

  GURL downloads_url(chrome::kChromeUIDownloadsURL);
  ui_test_utils::NavigateToURL(browser(), downloads_url);
  EXPECT_FALSE(command_updater->IsCommandEnabled(IDC_CREATE_SHORTCUTS));

  GURL blank_url(chrome::kAboutBlankURL);
  ui_test_utils::NavigateToURL(browser(), blank_url);
  EXPECT_FALSE(command_updater->IsCommandEnabled(IDC_CREATE_SHORTCUTS));
}
<commit_msg>enabled one browser test and tag JavascriptAlertActivatesTab, ReloadThenCancelBeforeUnload, & SingleBeforeUnloadAfterWindowClose as disabled so they compile but don't run on the Mac<commit_after>// Copyright (c) 2009 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include <string>

#include "app/l10n_util.h"
#include "base/sys_info.h"
#include "chrome/app/chrome_dll_resource.h"
#include "chrome/browser/app_modal_dialog.h"
#include "chrome/browser/browser.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/renderer_host/render_process_host.h"
#include "chrome/browser/tab_contents/tab_contents.h"
#include "chrome/common/url_constants.h"
#include "chrome/common/page_transition_types.h"
#include "chrome/test/in_process_browser_test.h"
#include "chrome/test/ui_test_utils.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "grit/chromium_strings.h"
#include "grit/generated_resources.h"

const std::string BEFORE_UNLOAD_HTML =
    "<title>beforeunload</title>"
    ""
    "";

const std::wstring OPEN_NEW_BEFOREUNLOAD_PAGE =
    L"w=window.open(); w.onbeforeunload=function(e){return 'foo'};";

namespace {

// Given a page title, returns the expected window caption string.
std::wstring WindowCaptionFromPageTitle(std::wstring page_title) {
#if defined(OS_MACOSX) || defined(OS_CHROMEOS)
  // On Mac or ChromeOS, we don't want to suffix the page title with
  // the application name.
  if (page_title.empty())
    return l10n_util::GetString(IDS_BROWSER_WINDOW_MAC_TAB_UNTITLED);
  return page_title;
#elif defined(OS_WIN) || defined(OS_LINUX)
  if (page_title.empty())
    return l10n_util::GetString(IDS_PRODUCT_NAME);

  return l10n_util::GetStringF(IDS_BROWSER_WINDOW_TITLE_FORMAT, page_title);
#endif
}

// Returns the number of active RenderProcessHosts.
int CountRenderProcessHosts() {
  int result = 0;
  for (RenderProcessHost::iterator i(RenderProcessHost::AllHostsIterator());
       !i.IsAtEnd(); i.Advance())
    ++result;
  return result;
}

}  // namespace

class BrowserTest : public InProcessBrowserTest {
 protected:
  // In RTL locales wrap the page title with RTL embedding characters so that it
  // matches the value returned by GetWindowTitle().
  std::wstring LocaleWindowCaptionFromPageTitle(
      const std::wstring& expected_title) {
    std::wstring page_title = WindowCaptionFromPageTitle(expected_title);
#if defined(OS_WIN)
    std::string locale = g_browser_process->GetApplicationLocale();
    if (l10n_util::GetTextDirectionForLocale(locale.c_str()) ==
        l10n_util::RIGHT_TO_LEFT) {
      l10n_util::WrapStringWithLTRFormatting(&page_title);
    }

    return page_title;
#else
    // Do we need to use the above code on POSIX as well?
    return page_title;
#endif
  }
};

// Launch the app on a page with no title, check that the app title was set
// correctly.
IN_PROC_BROWSER_TEST_F(BrowserTest, NoTitle) {
  ui_test_utils::NavigateToURL(browser(),
                               ui_test_utils::GetTestUrl(L".", L"title1.html"));
  EXPECT_EQ(LocaleWindowCaptionFromPageTitle(L"title1.html"),
            UTF16ToWideHack(browser()->GetWindowTitleForCurrentTab()));
  string16 tab_title;
  ASSERT_TRUE(ui_test_utils::GetCurrentTabTitle(browser(), &tab_title));
  EXPECT_EQ(ASCIIToUTF16("title1.html"), tab_title);
}

// Launch the app, navigate to a page with a title, check that the app title
// was set correctly.
IN_PROC_BROWSER_TEST_F(BrowserTest, Title) {
  ui_test_utils::NavigateToURL(browser(),
                               ui_test_utils::GetTestUrl(L".", L"title2.html"));
  const std::wstring test_title(L"Title Of Awesomeness");
  EXPECT_EQ(LocaleWindowCaptionFromPageTitle(test_title),
            UTF16ToWideHack(browser()->GetWindowTitleForCurrentTab()));
  string16 tab_title;
  ASSERT_TRUE(ui_test_utils::GetCurrentTabTitle(browser(), &tab_title));
  EXPECT_EQ(WideToUTF16(test_title), tab_title);
}

#if defined(OS_MACOSX)
// http://crbug.com//29424
#define JavascriptAlertActivatesTab DISABLED_JavascriptAlertActivatesTab
#endif

IN_PROC_BROWSER_TEST_F(BrowserTest, JavascriptAlertActivatesTab) {
  GURL url(ui_test_utils::GetTestUrl(L".", L"title1.html"));
  ui_test_utils::NavigateToURL(browser(), url);
  browser()->AddTabWithURL(url, GURL(), PageTransition::TYPED,
                           true, 0, false, NULL);
  EXPECT_EQ(2, browser()->tab_count());
  EXPECT_EQ(0, browser()->selected_index());
  TabContents* second_tab = browser()->GetTabContentsAt(1);
  ASSERT_TRUE(second_tab);
  second_tab->render_view_host()->ExecuteJavascriptInWebFrame(L"",
      L"alert('Activate!');");
  AppModalDialog* alert = ui_test_utils::WaitForAppModalDialog();
  alert->CloseModalDialog();
  EXPECT_EQ(2, browser()->tab_count());
  EXPECT_EQ(1, browser()->selected_index());
}

// Create 34 tabs and verify that a lot of processes have been created. The
// exact number of processes depends on the amount of memory. Previously we
// had a hard limit of 31 processes and this test is mainly directed at
// verifying that we don't crash when we pass this limit.
IN_PROC_BROWSER_TEST_F(BrowserTest, ThirtyFourTabs) {
  GURL url(ui_test_utils::GetTestUrl(L".", L"title2.html"));

  // There is one initial tab.
  for (int ix = 0; ix != 33; ++ix) {
    browser()->AddTabWithURL(url, GURL(), PageTransition::TYPED,
                             true, 0, false, NULL);
  }
  EXPECT_EQ(34, browser()->tab_count());

  // See browser\renderer_host\render_process_host.cc for the algorithm to
  // decide how many processes to create.
  if (base::SysInfo::AmountOfPhysicalMemoryMB() >= 2048) {
    EXPECT_GE(CountRenderProcessHosts(), 24);
  } else {
    EXPECT_LE(CountRenderProcessHosts(), 23);
  }
}

#if defined(OS_MACOSX)
// http://crbug.com//29424
#define ReloadThenCancelBeforeUnload DISABLED_ReloadThenCancelBeforeUnload
#endif

// Test for crbug.com/22004.  Reloading a page with a before unload handler and
// then canceling the dialog should not leave the throbber spinning.
IN_PROC_BROWSER_TEST_F(BrowserTest, ReloadThenCancelBeforeUnload) {
  GURL url("data:text/html," + BEFORE_UNLOAD_HTML);
  ui_test_utils::NavigateToURL(browser(), url);

  // Navigate to another page, but click cancel in the dialog.  Make sure that
  // the throbber stops spinning.
  browser()->Reload();
  AppModalDialog* alert = ui_test_utils::WaitForAppModalDialog();
  alert->CloseModalDialog();
  EXPECT_FALSE(browser()->GetSelectedTabContents()->is_loading());

  // Clear the beforeunload handler so the test can easily exit.
  browser()->GetSelectedTabContents()->render_view_host()->
      ExecuteJavascriptInWebFrame(L"", L"onbeforeunload=null;");
}

#if defined(OS_MACOSX)
// http://crbug.com//29424
#define MAYBE_SingleBeforeUnloadAfterWindowClose DISABLED_SingleBeforeUnloadAfterWindowClose
#else
#define MAYBE_SingleBeforeUnloadAfterWindowClose FLAKY_SingleBeforeUnloadAfterWindowClose
#endif

// Test for crbug.com/11647.  A page closed with window.close() should not have
// two beforeunload dialogs shown.
IN_PROC_BROWSER_TEST_F(BrowserTest, MAYBE_SingleBeforeUnloadAfterWindowClose) {
  browser()->GetSelectedTabContents()->render_view_host()->
      ExecuteJavascriptInWebFrame(L"", OPEN_NEW_BEFOREUNLOAD_PAGE);

  // Close the new window with JavaScript, which should show a single
  // beforeunload dialog.  Then show another alert, to make it easy to verify
  // that a second beforeunload dialog isn't shown.
  browser()->GetTabContentsAt(0)->render_view_host()->
      ExecuteJavascriptInWebFrame(L"", L"w.close(); alert('bar');");
  AppModalDialog* alert = ui_test_utils::WaitForAppModalDialog();
  alert->AcceptWindow();

  alert = ui_test_utils::WaitForAppModalDialog();
  EXPECT_FALSE(alert->is_before_unload_dialog());
  alert->AcceptWindow();
}

// Test that get_process_idle_time() returns reasonable values when compared
// with time deltas measured locally.
IN_PROC_BROWSER_TEST_F(BrowserTest, RenderIdleTime) {
  base::TimeTicks start = base::TimeTicks::Now();
  ui_test_utils::NavigateToURL(browser(),
                               ui_test_utils::GetTestUrl(L".", L"title1.html"));
  RenderProcessHost::iterator it(RenderProcessHost::AllHostsIterator());
  for (; !it.IsAtEnd(); it.Advance()) {
    base::TimeDelta renderer_td =
        it.GetCurrentValue()->get_child_process_idle_time();
    base::TimeDelta browser_td = base::TimeTicks::Now() - start;
    EXPECT_TRUE(browser_td >= renderer_td);
  }
}

// Test IDC_CREATE_SHORTCUTS command is enabled for url scheme file, ftp, http
// and https and disabled for chrome://, about:// etc.
IN_PROC_BROWSER_TEST_F(BrowserTest, CommandCreateAppShortcut) {
  static const wchar_t kDocRoot[] = L"chrome/test/data";

  CommandUpdater* command_updater = browser()->command_updater();

  // Urls that are okay to have shortcuts.
  GURL file_url(ui_test_utils::GetTestUrl(L".", L"empty.html"));
  ASSERT_TRUE(file_url.SchemeIs(chrome::kFileScheme));
  ui_test_utils::NavigateToURL(browser(), file_url);
  EXPECT_TRUE(command_updater->IsCommandEnabled(IDC_CREATE_SHORTCUTS));

  scoped_refptr<FTPTestServer> ftp_server(
        FTPTestServer::CreateServer(kDocRoot));
  ASSERT_TRUE(NULL != ftp_server.get());
  GURL ftp_url(ftp_server->TestServerPage(""));
  ASSERT_TRUE(ftp_url.SchemeIs(chrome::kFtpScheme));
  ui_test_utils::NavigateToURL(browser(), ftp_url);
  EXPECT_TRUE(command_updater->IsCommandEnabled(IDC_CREATE_SHORTCUTS));

  scoped_refptr<HTTPTestServer> http_server(
        HTTPTestServer::CreateServer(kDocRoot, NULL));
  ASSERT_TRUE(NULL != http_server.get());
  GURL http_url(http_server->TestServerPage(""));
  ASSERT_TRUE(http_url.SchemeIs(chrome::kHttpScheme));
  ui_test_utils::NavigateToURL(browser(), http_url);
  EXPECT_TRUE(command_updater->IsCommandEnabled(IDC_CREATE_SHORTCUTS));

  scoped_refptr<HTTPSTestServer> https_server(
        HTTPSTestServer::CreateGoodServer(kDocRoot));
  ASSERT_TRUE(NULL != https_server.get());
  GURL https_url(https_server->TestServerPage("/"));
  ASSERT_TRUE(https_url.SchemeIs(chrome::kHttpsScheme));
  ui_test_utils::NavigateToURL(browser(), https_url);
  EXPECT_TRUE(command_updater->IsCommandEnabled(IDC_CREATE_SHORTCUTS));

  // Urls that should not have shortcuts.
  GURL new_tab_url(chrome::kChromeUINewTabURL);
  ui_test_utils::NavigateToURL(browser(), new_tab_url);
  EXPECT_FALSE(command_updater->IsCommandEnabled(IDC_CREATE_SHORTCUTS));

  GURL history_url(chrome::kChromeUIHistoryURL);
  ui_test_utils::NavigateToURL(browser(), history_url);
  EXPECT_FALSE(command_updater->IsCommandEnabled(IDC_CREATE_SHORTCUTS));

  GURL downloads_url(chrome::kChromeUIDownloadsURL);
  ui_test_utils::NavigateToURL(browser(), downloads_url);
  EXPECT_FALSE(command_updater->IsCommandEnabled(IDC_CREATE_SHORTCUTS));

  GURL blank_url(chrome::kAboutBlankURL);
  ui_test_utils::NavigateToURL(browser(), blank_url);
  EXPECT_FALSE(command_updater->IsCommandEnabled(IDC_CREATE_SHORTCUTS));
}
<|endoftext|>


<commit_before>#ifndef __ABSTRACT_DOMAINS_HH__
#define __ABSTRACT_DOMAINS_HH__

#include "crab_llvm/crab_cfg.hh"

#include "crab/domains/linear_constraints.hpp"
#include "crab/domains/intervals.hpp"
#include "crab/domains/dis_intervals.hpp"
//#include "crab/domains/sparse_dbm.hpp"
#include "crab/domains/split_dbm.hpp"
#include "crab/domains/boxes.hpp"
#include "crab/domains/apron_domains.hpp"
#include "crab/domains/array_smashing.hpp"
#include "crab/domains/term_equiv.hpp"
#include "crab/domains/flat_boolean_domain.hpp"
#include "crab/domains/combined_domains.hpp"
#include "crab/domains/wrapped_interval_domain.hpp"
//#include "crab/domains/array_sparse_graph.hpp"
//#include "crab/domains/nullity.hpp"
//#include "crab/domains/diff_domain.hpp" /* only debugging */

/*
   Definition of the abstract domains (no instantiation done here)
*/

namespace crab_llvm {

  using namespace crab::domains;
  using namespace ikos;

  /* BEGIN MACROS only for internal use */
  // The base numerical domain
  #define BASE(DOM) base_ ## DOM
  // Array functor domain where the base domain is a reduced product
  // of a boolean domain with the numerical domain DOM.
  #define ARRAY_BOOL_NUM(DOM) \
    typedef array_smashing<flat_boolean_numerical_domain<BASE(DOM)>> DOM
  // Array functor domain where the base domain is DOM
  #define ARRAY_NUM(DOM) \
    typedef array_smashing<BASE(DOM)> DOM;
  /* END MACROS only for internal use */

  //////
  // Base domains
  //////

  /// -- Intervals
  #if 1
  typedef interval_domain<number_t, varname_t> BASE(interval_domain_t);
  #else
  // -- enable apron version for more precise backward operations
  typedef apron_domain<number_t, varname_t, apron_domain_id_t::APRON_INT>
  BASE(interval_domain_t);
  #endif
  /// -- Wrapped interval domain (APLAS'12)
  typedef wrapped_interval_domain<number_t, varname_t> BASE(wrapped_interval_domain_t);
  /// -- Zones using sparse DBMs (SAS'16)
  // typedef SpDBM_impl::DefaultParams<number_t> SparseDBMGraph;
  // typedef SparseDBM<number_t, varname_t, SparseDBMGraph> BASE(dbm_domain_t);
  /// -- Zones using sparse DBMs in split normal form (SAS'16)
  typedef SDBM_impl::DefaultParams<number_t> SplitDBMGraph;
  typedef SplitDBM<number_t, varname_t, SplitDBMGraph> BASE(split_dbm_domain_t);
  /// -- Boxes
  typedef boxes_domain<number_t, varname_t> BASE(boxes_domain_t);
  // typedef diff_domain<flat_boolean_numerical_domain<BASE(interval_domain_t)>,
  // 		         boxes_domain<number_t, varname_t> > BASE(boxes_domain_t);
  /// -- DisIntervals
  typedef dis_interval_domain <number_t, varname_t> BASE(dis_interval_domain_t);
  /// -- Elina/Apron domains
  typedef apron_domain<number_t, varname_t, apron_domain_id_t::APRON_OCT>
  BASE(opt_oct_apron_domain_t);
  typedef apron_domain<number_t, varname_t, apron_domain_id_t::APRON_PK>
  BASE(pk_apron_domain_t);
  /// -- Reduced product of intervals with congruences
  typedef numerical_congruence_domain<BASE(interval_domain_t)> BASE(ric_domain_t);
  /// -- Term functor domain with Intervals (VMCAI'16)
  typedef crab::cfg::var_factory_impl::str_var_alloc_col::varname_t str_varname_t;
  typedef interval_domain<number_t, str_varname_t> str_interval_dom_t;
  typedef term::TDomInfo<number_t, varname_t, str_interval_dom_t> idom_info;
  typedef term_domain<idom_info> BASE(term_int_domain_t);
  /// -- Term functor domain with DisIntervals (VMCAI'16)
  typedef dis_interval_domain<number_t, str_varname_t> str_dis_interval_dom_t;
  typedef term::TDomInfo<number_t, varname_t, str_dis_interval_dom_t> dis_idom_info;
  typedef term_domain<dis_idom_info> BASE(term_dis_int_domain_t);
  /// -- Reduced product of Term(DisIntervals) with split zones
  typedef reduced_numerical_domain_product2<BASE(term_dis_int_domain_t),
					    BASE(split_dbm_domain_t)> BASE(num_domain_t);

  ARRAY_BOOL_NUM(interval_domain_t);
  //ARRAY_BOOL_NUM(dbm_domain_t);
  ARRAY_BOOL_NUM(split_dbm_domain_t);
  ARRAY_BOOL_NUM(dis_interval_domain_t);
  ARRAY_BOOL_NUM(opt_oct_apron_domain_t);
  ARRAY_BOOL_NUM(pk_apron_domain_t);
  ARRAY_BOOL_NUM(ric_domain_t);
  ARRAY_BOOL_NUM(term_int_domain_t);
  ARRAY_BOOL_NUM(term_dis_int_domain_t);
  ARRAY_BOOL_NUM(num_domain_t);
  // Boxes can reason natively about booleans so that's why we don't
  // combine it with a boolean domain.
  ARRAY_NUM(boxes_domain_t);
  /* domains that preserve machine arithmetic semantics */
  ARRAY_BOOL_NUM(wrapped_interval_domain_t);

} // end namespace crab-llvm

#endif
<commit_msg>Switch to optimized reduction for terms x dbm domain<commit_after>#ifndef __ABSTRACT_DOMAINS_HH__
#define __ABSTRACT_DOMAINS_HH__

#include "crab_llvm/crab_cfg.hh"

#include "crab/domains/linear_constraints.hpp"
#include "crab/domains/intervals.hpp"
#include "crab/domains/dis_intervals.hpp"
//#include "crab/domains/sparse_dbm.hpp"
#include "crab/domains/split_dbm.hpp"
#include "crab/domains/boxes.hpp"
#include "crab/domains/apron_domains.hpp"
#include "crab/domains/array_smashing.hpp"
#include "crab/domains/term_equiv.hpp"
#include "crab/domains/flat_boolean_domain.hpp"
#include "crab/domains/combined_domains.hpp"
#include "crab/domains/wrapped_interval_domain.hpp"
//#include "crab/domains/array_sparse_graph.hpp"
//#include "crab/domains/nullity.hpp"
//#include "crab/domains/diff_domain.hpp" /* only debugging */

/*
   Definition of the abstract domains (no instantiation done here)
*/

namespace crab_llvm {

  using namespace crab::domains;
  using namespace ikos;

  /* BEGIN MACROS only for internal use */
  // The base numerical domain
  #define BASE(DOM) base_ ## DOM
  // Array functor domain where the base domain is a reduced product
  // of a boolean domain with the numerical domain DOM.
  #define ARRAY_BOOL_NUM(DOM) \
    typedef array_smashing<flat_boolean_numerical_domain<BASE(DOM)>> DOM
  // Array functor domain where the base domain is DOM
  #define ARRAY_NUM(DOM) \
    typedef array_smashing<BASE(DOM)> DOM;
  /* END MACROS only for internal use */

  //////
  // Base domains
  //////

  /// -- Intervals
  #if 1
  typedef interval_domain<number_t, varname_t> BASE(interval_domain_t);
  #else
  // -- enable apron version for more precise backward operations
  typedef apron_domain<number_t, varname_t, apron_domain_id_t::APRON_INT>
  BASE(interval_domain_t);
  #endif
  /// -- Wrapped interval domain (APLAS'12)
  typedef wrapped_interval_domain<number_t, varname_t> BASE(wrapped_interval_domain_t);
  /// -- Zones using sparse DBMs (SAS'16)
  // typedef SpDBM_impl::DefaultParams<number_t> SparseDBMGraph;
  // typedef SparseDBM<number_t, varname_t, SparseDBMGraph> BASE(dbm_domain_t);
  /// -- Zones using sparse DBMs in split normal form (SAS'16)
  typedef SDBM_impl::DefaultParams<number_t> SplitDBMGraph;
  typedef SplitDBM<number_t, varname_t, SplitDBMGraph> BASE(split_dbm_domain_t);
  /// -- Boxes
  typedef boxes_domain<number_t, varname_t> BASE(boxes_domain_t);
  // typedef diff_domain<flat_boolean_numerical_domain<BASE(interval_domain_t)>,
  // 		         boxes_domain<number_t, varname_t> > BASE(boxes_domain_t);
  /// -- DisIntervals
  typedef dis_interval_domain <number_t, varname_t> BASE(dis_interval_domain_t);
  /// -- Elina/Apron domains
  typedef apron_domain<number_t, varname_t, apron_domain_id_t::APRON_OCT>
  BASE(opt_oct_apron_domain_t);
  typedef apron_domain<number_t, varname_t, apron_domain_id_t::APRON_PK>
  BASE(pk_apron_domain_t);
  /// -- Reduced product of intervals with congruences
  typedef numerical_congruence_domain<BASE(interval_domain_t)> BASE(ric_domain_t);
  /// -- Term functor domain with Intervals (VMCAI'16)
  typedef crab::cfg::var_factory_impl::str_var_alloc_col::varname_t str_varname_t;
  typedef interval_domain<number_t, str_varname_t> str_interval_dom_t;
  typedef term::TDomInfo<number_t, varname_t, str_interval_dom_t> idom_info;
  typedef term_domain<idom_info> BASE(term_int_domain_t);
  /// -- Term functor domain with DisIntervals (VMCAI'16)
  typedef dis_interval_domain<number_t, str_varname_t> str_dis_interval_dom_t;
  typedef term::TDomInfo<number_t, varname_t, str_dis_interval_dom_t> dis_idom_info;
  typedef term_domain<dis_idom_info> BASE(term_dis_int_domain_t);
  /// -- Reduced product of Term(DisIntervals) with split zones
  typedef reduced_numerical_domain_product2<BASE(term_dis_int_domain_t),
					    BASE(split_dbm_domain_t),
					    reduced_product_impl::term_dbm_params> BASE(num_domain_t);

  ARRAY_BOOL_NUM(interval_domain_t);
  //ARRAY_BOOL_NUM(dbm_domain_t);
  ARRAY_BOOL_NUM(split_dbm_domain_t);
  ARRAY_BOOL_NUM(dis_interval_domain_t);
  ARRAY_BOOL_NUM(opt_oct_apron_domain_t);
  ARRAY_BOOL_NUM(pk_apron_domain_t);
  ARRAY_BOOL_NUM(ric_domain_t);
  ARRAY_BOOL_NUM(term_int_domain_t);
  ARRAY_BOOL_NUM(term_dis_int_domain_t);
  ARRAY_BOOL_NUM(num_domain_t);
  // Boxes can reason natively about booleans so that's why we don't
  // combine it with a boolean domain.
  ARRAY_NUM(boxes_domain_t);
  /* domains that preserve machine arithmetic semantics */
  ARRAY_BOOL_NUM(wrapped_interval_domain_t);

} // end namespace crab-llvm

#endif
<|endoftext|>


<commit_before>/**
 * Non-metric Space Library
 *
 * Authors: Bilegsaikhan Naidan (https://github.com/bileg), Leonid Boytsov (http://boytsov.info).
 * With contributions from Lawrence Cayton (http://lcayton.com/) and others.
 *
 * For the complete list of contributors and further details see:
 * https://github.com/searchivarius/NonMetricSpaceLib
 *
 * Copyright (c) 2016
 *
 * This code is released under the
 * Apache License Version 2.0 http://www.apache.org/licenses/.
 *
 */

#include <cmath>

#include "space.h"
#include "rangequery.h"
#include "knnquery.h"

#include <string>

using namespace std;

#include <space/space_sparse_vector_inter.h>
#include <space/space_vector.h>

#include "method/falconn.h"

const string PARAM_HASH_FAMILY                = "hash_family";
const string PARAM_HASH_FAMILY_CROSS_POLYTOPE = "cross_polytope";
const string PARAM_HASH_FAMILY_HYPERPLANE     = "hyperplane";

const string PARAM_STORAGE_HASH_TABLE   = "storage_hash_table";
const string PARAM_NUM_HASH_BITS        = "num_hash_bits";
const string PARAM_NUM_HASH_TABLES      = "num_hash_tables";
const string PARAM_NUM_PROBES           = "num_probes"; // This is going to be a query-time parameter
const string PARAM_NUM_ROTATIONS        = "num_rotations";
const string PARAM_SEED                 = "seed";
const string PARAM_FEATURE_HASHING_DIM  = "feature_hashing_dimension";
const string PARAM_NORM_DATA            = "norm_data";

namespace similarity {

using namespace falconn;

// storage_hash_table_from_string is a modification of FALCONN's python_wrapper.h
StorageHashTable storage_hash_table_from_string(string str) {
  ToLower(str);
  for (int ii = 0; ii < static_cast<int>(kStorageHashTableStrings.size());
       ++ii) {
    if (str == kStorageHashTableStrings[ii]) {
      return StorageHashTable(ii);
    }
  }
  stringstream err;
  err << "Unknown value of the parameter " << PARAM_STORAGE_HASH_TABLE << " valid values are: ";
  for (int ii = 0; ii < static_cast<int>(kStorageHashTableStrings.size()); ++ii) {
    if (ii) err << ",";
    err << kStorageHashTableStrings[ii];
  }
  throw runtime_error(err.str());
}

template <typename dist_t>
 void FALCONN<dist_t>::createDenseDataPoint(const Object* o, DenseFalconnPoint& p, bool normData) const {
  CHECK(sizeof(dist_t)*dim_ == o->datalength());
  const dist_t *pVect = reinterpret_cast<const dist_t*>(o->data());
  for (size_t i = 0; i < dim_; ++i) {
    p[i] = pVect[i];
  }
  if (normData) {
    p.normalize();
  }
}

template <typename dist_t>
void FALCONN<dist_t>::createSparseDataPoint(const Object* o, SparseFalconnPoint& p, bool normData) const {
  p.clear();
  vector<SparseVectElem<dist_t>> target;
  UnpackSparseElements(o->data(), o->datalength(), target);

  dist_t norm = 1;
  if (normData) {
    norm = 0;
    for (const SparseVectElem<dist_t>& e : target) {
      norm += e.val_ *e.val_;
    }
    norm = 1/ sqrt(norm);
  }
  for (const SparseVectElem<dist_t>& e : target) {
    p.push_back(make_pair(e.id_, e.val_ * norm));
  }
#if 1
  dist_t s = 0;
  for (auto e: p) s += e.second * e.second;
  LOG(LIB_INFO) << "@@@@@@@@@@ NORM SQ: " << s;
#endif
}

template <typename dist_t>
void FALCONN<dist_t>::copyData(bool normData) {
  SpaceSparseVectorInter<dist_t>* pSparseSpace = dynamic_cast<SpaceSparseVectorInter<dist_t>*>(&space_);
  VectorSpace<dist_t>*            pDenseSpace  = dynamic_cast<VectorSpace<dist_t>*>(&space_);

  if (data_.empty()) return;
  if (pSparseSpace == nullptr && pDenseSpace == nullptr) {
    throw runtime_error("Only sparse and dense vector spaces are supported!");
  }
  if (pSparseSpace != nullptr) {
    LOG(LIB_INFO) << "Creating a sparse vector data set!";
    sparse_ = true;
    SparseFalconnPoint p;
    for (const Object* o: data_) {
      createSparseDataPoint(o, p, normData);
      falconn_data_sparse_.push_back(p);
    }
  }
  if (pDenseSpace != nullptr) {
    LOG(LIB_INFO) << "Creating a dense vector data set!";
    dim_ = data_[0]->datalength() / sizeof(dist_t);
    DenseFalconnPoint p(dim_);
    for (const Object* o: data_) {
      createDenseDataPoint(o, p, normData);
      falconn_data_dense_.emplace_back(p);
    }
  }
}

template <typename dist_t>
FALCONN<dist_t>::FALCONN(Space<dist_t>& space,
                         const ObjectVector& data) : data_(data), space_(space), sparse_(false),
                                                     dim_(0), num_probes_(10) {
}

template <typename dist_t>
void FALCONN<dist_t>::CreateIndex(const AnyParams& IndexParams)  {
  AnyParamManager  pmgr(IndexParams);

  LSHConstructionParameters params;
  params.distance_function = DistanceFunction::EuclideanSquared;
  // we want to use all the available threads to set up
  params.num_setup_threads = 0;

  norm_data_ = true;

  pmgr.GetParamOptional(PARAM_NORM_DATA, norm_data_, true);

  copyData(norm_data_);

  pmgr.GetParamOptional(PARAM_SEED, params.seed, 4057218);

  {
    string hash_table_storage_type;
    ToLower(hash_table_storage_type);
    // The flat hash table seems to be the most efficient
    pmgr.GetParamOptional(PARAM_STORAGE_HASH_TABLE, hash_table_storage_type, "flat_hash_table");
    params.storage_hash_table = storage_hash_table_from_string(hash_table_storage_type);
  }

  {
    string lsh_family_str;
    pmgr.GetParamOptional(PARAM_HASH_FAMILY, lsh_family_str, PARAM_HASH_FAMILY_CROSS_POLYTOPE);
    ToLower(lsh_family_str);
    if (lsh_family_str == PARAM_HASH_FAMILY_CROSS_POLYTOPE) {
      params.lsh_family = LSHFamily::CrossPolytope;
    } else if (lsh_family_str == PARAM_HASH_FAMILY_HYPERPLANE) {
      params.lsh_family = LSHFamily::Hyperplane;
    } else {
      PREPARE_RUNTIME_ERR(err)
      << "Unrecognized value of " << PARAM_HASH_FAMILY << " expected one of: "
      << PARAM_HASH_FAMILY_CROSS_POLYTOPE << ", " << PARAM_HASH_FAMILY_HYPERPLANE;
      THROW_RUNTIME_ERR(err);
    }
  }

  /*
   * The number of hash tables affects the memory usage. According to FALCONN's manual,
   * the larger it is, the better (unless it's too large).
   * They also recommend to start with a small number, e.g., 10-50 tables,
   * and then increase it gradually, while observing the effect it makes.
   */
  pmgr.GetParamOptional(PARAM_NUM_HASH_TABLES, params.l, 50);
  /*
   * This parameter controls the number of buckets per table,
   * According to FALCONN's manual, it should be approx. equal to
   * the binary logarithm of the number of data points
   */
  size_t num_hash_bits = max<size_t>(2, static_cast<size_t>(ceil(log2(data_.size()))));
  pmgr.GetParamOptional(PARAM_NUM_HASH_BITS, num_hash_bits, num_hash_bits);

  /*
   *  Number of rotations controls the number of pseudo-random rotations for
   *  the cross-polytope LSH, FALCONN's manual advised to set it to 1 for the dense data,
   *  and 2 for the sparse data.
   */
  size_t num_rotations_default = sparse_ ? 2 : 1;
  pmgr.GetParamOptional(PARAM_NUM_ROTATIONS, params.num_rotations, num_rotations_default);

  if (!sparse_) {
    params.dimension = dim_;
    compute_number_of_hash_functions<DenseFalconnPoint>(num_hash_bits, &params);
    falconn_table_dense_ = construct_table<DenseFalconnPoint>(falconn_data_dense_, params);
  } else {
    pmgr.GetParamRequired(PARAM_FEATURE_HASHING_DIM, params.feature_hashing_dimension);
    compute_number_of_hash_functions<SparseFalconnPoint>(num_hash_bits, &params);
    falconn_table_sparse_ = construct_table<SparseFalconnPoint>(falconn_data_sparse_, params);
  }

  // Check if a user specified extra parameters, which can be also misspelled variants of existing ones
  pmgr.CheckUnused();
  // Always call ResetQueryTimeParams() to set query-time parameters to their default values
  this->ResetQueryTimeParams();
}

template <typename dist_t>
void FALCONN<dist_t>::Search(KNNQuery<dist_t>* query, IdType) const {
  vector<IdType> ids;

  if (sparse_) {
    SparseFalconnPoint sparseQ;
    createSparseDataPoint(query->QueryObject(), sparseQ, norm_data_);
    falconn_table_sparse_->find_k_nearest_neighbors(sparseQ, query->GetK(), &ids);
  } else {
    DenseFalconnPoint  denseQ(dim_);
    createDenseDataPoint(query->QueryObject(), denseQ, norm_data_);
    falconn_table_dense_->find_k_nearest_neighbors(denseQ, query->GetK(), &ids);
  }
  // Recomputing distances for k nearest neighbors should have a very small impact on overall performance
  for (IdType ii : ids) {
    query->CheckAndAddToResult(data_[ii]);
  }
}

template <typename dist_t>
void
FALCONN<dist_t>::SetQueryTimeParams(const AnyParams& QueryTimeParams) {
  AnyParamManager pmgr(QueryTimeParams);

  pmgr.GetParamOptional(PARAM_NUM_PROBES, num_probes_, num_probes_);
  LOG(LIB_INFO) << PARAM_NUM_PROBES << " = " << num_probes_;
  if (sparse_) falconn_table_sparse_->set_num_probes(num_probes_);
  else falconn_table_dense_->set_num_probes(num_probes_);
  pmgr.CheckUnused();
}

template class FALCONN<float>;
template class FALCONN<double>;

}
<commit_msg>fully working FALCONN, but without data centering.<commit_after>/**
 * Non-metric Space Library
 *
 * Authors: Bilegsaikhan Naidan (https://github.com/bileg), Leonid Boytsov (http://boytsov.info).
 * With contributions from Lawrence Cayton (http://lcayton.com/) and others.
 *
 * For the complete list of contributors and further details see:
 * https://github.com/searchivarius/NonMetricSpaceLib
 *
 * Copyright (c) 2016
 *
 * This code is released under the
 * Apache License Version 2.0 http://www.apache.org/licenses/.
 *
 */

#include <cmath>

#include "space.h"
#include "rangequery.h"
#include "knnquery.h"

#include <string>

using namespace std;

#include <space/space_sparse_vector_inter.h>
#include <space/space_vector.h>

#include "method/falconn.h"

const string PARAM_HASH_FAMILY                = "hash_family";
const string PARAM_HASH_FAMILY_CROSS_POLYTOPE = "cross_polytope";
const string PARAM_HASH_FAMILY_HYPERPLANE     = "hyperplane";

const string PARAM_STORAGE_HASH_TABLE   = "storage_hash_table";
const string PARAM_NUM_HASH_BITS        = "num_hash_bits";
const string PARAM_NUM_HASH_TABLES      = "num_hash_tables";
const string PARAM_NUM_PROBES           = "num_probes"; // This is going to be a query-time parameter
const string PARAM_NUM_ROTATIONS        = "num_rotations";
const string PARAM_SEED                 = "seed";
const string PARAM_FEATURE_HASHING_DIM  = "feature_hashing_dimension";
const string PARAM_NORM_DATA            = "norm_data";

namespace similarity {

using namespace falconn;

// storage_hash_table_from_string is a modification of FALCONN's python_wrapper.h
StorageHashTable storage_hash_table_from_string(string str) {
  ToLower(str);
  for (int ii = 0; ii < static_cast<int>(kStorageHashTableStrings.size());
       ++ii) {
    if (str == kStorageHashTableStrings[ii]) {
      return StorageHashTable(ii);
    }
  }
  stringstream err;
  err << "Unknown value of the parameter " << PARAM_STORAGE_HASH_TABLE << " valid values are: ";
  for (int ii = 0; ii < static_cast<int>(kStorageHashTableStrings.size()); ++ii) {
    if (ii) err << ",";
    err << kStorageHashTableStrings[ii];
  }
  throw runtime_error(err.str());
}

template <typename dist_t>
 void FALCONN<dist_t>::createDenseDataPoint(const Object* o, DenseFalconnPoint& p, bool normData) const {
  CHECK(sizeof(dist_t)*dim_ == o->datalength());
  const dist_t *pVect = reinterpret_cast<const dist_t*>(o->data());
  for (size_t i = 0; i < dim_; ++i) {
    p[i] = pVect[i];
  }
  if (normData) {
    p.normalize();
  }
}

template <typename dist_t>
void FALCONN<dist_t>::createSparseDataPoint(const Object* o, SparseFalconnPoint& p, bool normData) const {
  p.clear();
  vector<SparseVectElem<dist_t>> target;
  UnpackSparseElements(o->data(), o->datalength(), target);

  dist_t norm = 1;
  if (normData) {
    norm = 0;
    for (const SparseVectElem<dist_t>& e : target) {
      norm += e.val_ *e.val_;
    }
    norm = 1/ sqrt(norm);
  }
  for (const SparseVectElem<dist_t>& e : target) {
    p.push_back(make_pair(e.id_, e.val_ * norm));
  }
#if 1
  dist_t s = 0;
  for (auto e: p) s += e.second * e.second;
  LOG(LIB_INFO) << "@@@@@@@@@@ NORM SQ: " << s;
#endif
}

template <typename dist_t>
void FALCONN<dist_t>::copyData(bool normData) {
  SpaceSparseVectorInter<dist_t>* pSparseSpace = dynamic_cast<SpaceSparseVectorInter<dist_t>*>(&space_);
  VectorSpace<dist_t>*            pDenseSpace  = dynamic_cast<VectorSpace<dist_t>*>(&space_);

  if (data_.empty()) return;
  if (pSparseSpace == nullptr && pDenseSpace == nullptr) {
    throw runtime_error("Only sparse and dense vector spaces are supported!");
  }
  if (pSparseSpace != nullptr) {
    LOG(LIB_INFO) << "Copying a sparse vector data set.";
    sparse_ = true;
    SparseFalconnPoint p;
    for (const Object* o: data_) {
      createSparseDataPoint(o, p, normData);
      falconn_data_sparse_.push_back(p);
    }
  }
  if (pDenseSpace != nullptr) {
    LOG(LIB_INFO) << "Copying a dense vector data set.";
    dim_ = data_[0]->datalength() / sizeof(dist_t);
    DenseFalconnPoint p(dim_);
    for (const Object* o: data_) {
      createDenseDataPoint(o, p, normData);
      falconn_data_dense_.emplace_back(p);
    }
  }
  LOG(LIB_INFO) << "Dataset is copied.";
}

template <typename dist_t>
FALCONN<dist_t>::FALCONN(Space<dist_t>& space,
                         const ObjectVector& data) : data_(data), space_(space), sparse_(false),
                                                     dim_(0), num_probes_(10) {
}

template <typename dist_t>
void FALCONN<dist_t>::CreateIndex(const AnyParams& IndexParams)  {
  AnyParamManager  pmgr(IndexParams);

  LSHConstructionParameters params;
  params.distance_function = DistanceFunction::EuclideanSquared;
  // we want to use all the available threads to set up
  params.num_setup_threads = 0;

  norm_data_ = true;

  pmgr.GetParamOptional(PARAM_NORM_DATA, norm_data_, true);

  copyData(norm_data_);

  pmgr.GetParamOptional(PARAM_SEED, params.seed, 4057218);

  {
    string hash_table_storage_type;
    ToLower(hash_table_storage_type);
    // The flat hash table seems to be the most efficient
    pmgr.GetParamOptional(PARAM_STORAGE_HASH_TABLE, hash_table_storage_type, "flat_hash_table");
    params.storage_hash_table = storage_hash_table_from_string(hash_table_storage_type);
  }

  {
    string lsh_family_str;
    pmgr.GetParamOptional(PARAM_HASH_FAMILY, lsh_family_str, PARAM_HASH_FAMILY_CROSS_POLYTOPE);
    ToLower(lsh_family_str);
    if (lsh_family_str == PARAM_HASH_FAMILY_CROSS_POLYTOPE) {
      params.lsh_family = LSHFamily::CrossPolytope;
    } else if (lsh_family_str == PARAM_HASH_FAMILY_HYPERPLANE) {
      params.lsh_family = LSHFamily::Hyperplane;
    } else {
      PREPARE_RUNTIME_ERR(err)
      << "Unrecognized value of " << PARAM_HASH_FAMILY << " expected one of: "
      << PARAM_HASH_FAMILY_CROSS_POLYTOPE << ", " << PARAM_HASH_FAMILY_HYPERPLANE;
      THROW_RUNTIME_ERR(err);
    }
  }

  /*
   * The number of hash tables affects the memory usage. According to FALCONN's manual,
   * the larger it is, the better (unless it's too large).
   * They also recommend to start with a small number, e.g., 10-50 tables,
   * and then increase it gradually, while observing the effect it makes.
   */
  pmgr.GetParamOptional(PARAM_NUM_HASH_TABLES, params.l, 50);
  /*
   * This parameter controls the number of buckets per table,
   * According to FALCONN's manual, it should be approx. equal to
   * the binary logarithm of the number of data points
   */
  size_t num_hash_bits = max<size_t>(2, static_cast<size_t>(floor(log2(data_.size()>>1))));
  pmgr.GetParamOptional(PARAM_NUM_HASH_BITS, num_hash_bits, num_hash_bits);

  /*
   *  Number of rotations controls the number of pseudo-random rotations for
   *  the cross-polytope LSH, FALCONN's manual advised to set it to 1 for the dense data,
   *  and 2 for the sparse data.
   */
  size_t num_rotations_default = sparse_ ? 2 : 1;
  pmgr.GetParamOptional(PARAM_NUM_ROTATIONS, params.num_rotations, num_rotations_default);

  if (!sparse_) {
    params.dimension = dim_;
    compute_number_of_hash_functions<DenseFalconnPoint>(num_hash_bits, &params);
    falconn_table_dense_ = construct_table<DenseFalconnPoint>(falconn_data_dense_, params);
  } else {
    pmgr.GetParamRequired(PARAM_FEATURE_HASHING_DIM, params.feature_hashing_dimension);
    compute_number_of_hash_functions<SparseFalconnPoint>(num_hash_bits, &params);
    falconn_table_sparse_ = construct_table<SparseFalconnPoint>(falconn_data_sparse_, params);
  }

  LOG(LIB_INFO) << "Normalize data?:      " << norm_data_;
  LOG(LIB_INFO) << "#dim:                 " << params.dimension;
  LOG(LIB_INFO) << "#of feature-hash dim: " << params.feature_hashing_dimension;

  LOG(LIB_INFO) << "Hash family:          " << kLSHFamilyStrings[(size_t)params.lsh_family];
  LOG(LIB_INFO) << "Table storage type:   " << kStorageHashTableStrings[(size_t)params.storage_hash_table];

  LOG(LIB_INFO) << "#of hash tables:      " << params.k;
  LOG(LIB_INFO) << "#of hash bits:        " << num_hash_bits;
  LOG(LIB_INFO) << "#of rotations:        " << params.num_rotations;

  LOG(LIB_INFO) << "seed:                 " << params.seed;

  // Check if a user specified extra parameters, which can be also misspelled variants of existing ones
  pmgr.CheckUnused();
  // Always call ResetQueryTimeParams() to set query-time parameters to their default values
  this->ResetQueryTimeParams();
}

template <typename dist_t>
void FALCONN<dist_t>::Search(KNNQuery<dist_t>* query, IdType) const {
  vector<IdType> ids;

  if (sparse_) {
    SparseFalconnPoint sparseQ;
    createSparseDataPoint(query->QueryObject(), sparseQ, norm_data_);
    falconn_table_sparse_->find_k_nearest_neighbors(sparseQ, query->GetK(), &ids);
  } else {
    DenseFalconnPoint  denseQ(dim_);
    createDenseDataPoint(query->QueryObject(), denseQ, norm_data_);
    falconn_table_dense_->find_k_nearest_neighbors(denseQ, query->GetK(), &ids);
  }
  // Recomputing distances for k nearest neighbors should have a very small impact on overall performance
  for (IdType ii : ids) {
    query->CheckAndAddToResult(data_[ii]);
  }
}

template <typename dist_t>
void
FALCONN<dist_t>::SetQueryTimeParams(const AnyParams& QueryTimeParams) {
  AnyParamManager pmgr(QueryTimeParams);

  pmgr.GetParamOptional(PARAM_NUM_PROBES, num_probes_, num_probes_);
  LOG(LIB_INFO) << PARAM_NUM_PROBES << " = " << num_probes_;
  if (sparse_) falconn_table_sparse_->set_num_probes(num_probes_);
  else falconn_table_dense_->set_num_probes(num_probes_);
  pmgr.CheckUnused();
}

template class FALCONN<float>;
template class FALCONN<double>;

}
<|endoftext|>


<commit_before>/**
 * Clever programming language
 * Copyright (c) 2011-2012 Clever Team
 *
 * 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.
 */

#include <iostream>
#include "compiler/clever.h"
#include "interpreter/driver.h"
#ifdef _WIN32
#include "win32/win32.h"
#endif

#define MORE_ARG() \
	if (!(++i < argc)) { \
		std::cerr << "Missing parameter for option " << argv[i-1] << std::endl; \
		exit(1); \
	}

static void show_usage()
{
	std::cout << "Usage: clever <options> [filename]" << std::endl;
	std::cout << std::endl;

	std::cout << "General options:" << std::endl;
#ifdef _WIN32
	std::cout << "\t-b\tRun on background" << std::endl;
#endif
	std::cout << "\t-h\tHelp" << std::endl;
	std::cout << "\t-v\tShow version" << std::endl;
	std::cout << std::endl;

	std::cout << "Code options (must be the last one and unique):" << std::endl;
	std::cout << "\t-i\tRun the interative mode" << std::endl;
	std::cout << "\t-r\tRun the code" << std::endl;
	std::cout << "\t-qr\tQuickly run the code (import std automatically)" << std::endl;
	std::cout << std::endl;

#ifdef CLEVER_DEBUG
	std::cout << "Debug options:" << std::endl;
	std::cout << "\t-p\tTrace parsing" << std::endl;
	std::cout << "\t-d\tDump opcode" << std::endl;
	std::cout << std::endl;
#endif
}

int main(int argc, char **argv)
{
	clever::Interpreter clever(&argc, &argv);

	if (argc == 1) {
		std::cout << "Clever Programming Language" << std::endl;
		show_usage();
		return 0;
	}

	int inc_arg = 0;

	for (int i = 1; i < argc; ++i) {
		// Look for general options, then code options and finally debug options.
		if (argv[i] == std::string("-h")) {
			show_usage();
			return 0;
		} else if (argv[i] == std::string("-v")) {
			std::cout << "Clever - development version";
#ifdef CLEVER_DEBUG
			std::cout << " (debug)";
#endif
			std::cout << std::endl;

			std::cout << "Copyright (c) 2011-2012 Clever Team" << std::endl;
			std::cout << "(built: " __DATE__ " " __TIME__ ")" << std::endl;
			return 0;
#ifdef _WIN32
		} else if (argv[i] == std::string("-b")) {
			if (GetConsoleWindow()) {
				std::string cline;

				for (int j = 0; j < argc; ++j) {
					if (argv[j] != std::string("-b")) {
						cline = cline + std::string(argv[j]) + " ";
					}
				}

				CreateBackgroundProcess(cline);
				return 0;
			}
#endif
		} else if (argv[i] == std::string("-i")) {
			std::string input_line;
			inc_arg++;
			while (std::cin) {
				getline(std::cin, input_line);
				if (clever.loadStr(input_line + '\n', false) == 0) {
					clever.execute(true);
				}
  			}
  			clever.shutdown();
  			return 0;
		} else if (argv[i] == std::string("-r")) {
			MORE_ARG();
			inc_arg++;
			if (clever.loadStr(argv[i], false)) {
				clever.shutdown();
				exit(1);
			}
			break;
		} else if (argv[i] == std::string("-qr")) {
			MORE_ARG();
			inc_arg++;
			if (clever.loadStr(argv[i], true)) {
				clever.shutdown();
				exit(1);
			}
			break;
#ifdef CLEVER_DEBUG
		} else if (argv[i] == std::string("-p")) {
			inc_arg++;
			clever.setTraceParsing(true);
		} else if (argv[i] == std::string("-d")) {
			inc_arg++;
#endif
		} else if (argv[i][0] == '-') {
			std::cerr << "Unknown option '" << argv[i] << "'" << std::endl;
			exit(1);
		} else {
			clever.loadFile(argv[i]);
			break;
		}
	}

	argc -= inc_arg + 1;
	argv += inc_arg + 1;

	clever.execute(false);
	clever.shutdown();

	return 0;
}
<commit_msg>- Removed excessive std::cout/std::endl usage in main.cc<commit_after>/**
 * Clever programming language
 * Copyright (c) 2011-2012 Clever Team
 *
 * 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.
 */

#include <iostream>
#include "compiler/clever.h"
#include "interpreter/driver.h"
#ifdef _WIN32
#include "win32/win32.h"
#endif

#define MORE_ARG() \
	if (!(++i < argc)) { \
		std::cerr << "Missing parameter for option " << argv[i-1] << std::endl; \
		exit(1); \
	}

static void show_usage()
{
    std::cout << "Usage: clever <options> [filename]\n\n"
                 "General options:\n";

#ifdef _WIN32
    std::cout << "\t-b\tRun on background\n";
#endif

    std::cout << "\t-h\tHelp\n"
                 "\t-v\tShow version\n"
                 "\n";

    std::cout << "Code options (must be the last one and unique):\n"
                 "\t-i\tRun the interative mode\n"
                 "\t-r\tRun the code\n"
                 "\t-qr\tQuickly run the code (import std automatically)\n"
                 "\n";

#ifdef CLEVER_DEBUG
    std::cout << "Debug options:\n"
                 "\t-p\tTrace parsing\n"
                 "\t-d\tDump opcode\n"
                 "\n";
#endif
}

int main(int argc, char **argv)
{
    clever::Interpreter clever(&argc, &argv);

	if (argc == 1) {
		std::cout << "Clever Programming Language" << std::endl;
		show_usage();
		return 0;
	}

    int inc_arg = 0;

    for (int i = 1; i < argc; ++i) {
		// Look for general options, then code options and finally debug options.
		if (argv[i] == std::string("-h")) {
			show_usage();
			return 0;
		} else if (argv[i] == std::string("-v")) {
            std::cout << "Clever - development version";

#ifdef CLEVER_DEBUG
            std::cout << " (debug)";
#endif
            std::cout << "\n"
                         "Copyright (c) 2011-2012 Clever Team\n"
                         "(built: " __DATE__ " " __TIME__ ")\n";

			return 0;
#ifdef _WIN32
		} else if (argv[i] == std::string("-b")) {
			if (GetConsoleWindow()) {
				std::string cline;

				for (int j = 0; j < argc; ++j) {
					if (argv[j] != std::string("-b")) {
						cline = cline + std::string(argv[j]) + " ";
					}
				}

				CreateBackgroundProcess(cline);
				return 0;
			}
#endif
		} else if (argv[i] == std::string("-i")) {
			std::string input_line;
			inc_arg++;
			while (std::cin) {
				getline(std::cin, input_line);
				if (clever.loadStr(input_line + '\n', false) == 0) {
					clever.execute(true);
				}
  			}
  			clever.shutdown();
  			return 0;
		} else if (argv[i] == std::string("-r")) {
			MORE_ARG();
			inc_arg++;
			if (clever.loadStr(argv[i], false)) {
				clever.shutdown();
				exit(1);
			}
			break;
		} else if (argv[i] == std::string("-qr")) {
			MORE_ARG();
			inc_arg++;
			if (clever.loadStr(argv[i], true)) {
				clever.shutdown();
				exit(1);
			}
			break;
#ifdef CLEVER_DEBUG
		} else if (argv[i] == std::string("-p")) {
			inc_arg++;
			clever.setTraceParsing(true);
		} else if (argv[i] == std::string("-d")) {
			inc_arg++;
#endif
		} else if (argv[i][0] == '-') {
			std::cerr << "Unknown option '" << argv[i] << "'" << std::endl;
			exit(1);
		} else {
			clever.loadFile(argv[i]);
			break;
		}
	}

	argc -= inc_arg + 1;
	argv += inc_arg + 1;

	clever.execute(false);
    clever.shutdown();

	return 0;
}
<|endoftext|>


<commit_before><commit_msg>Fix another string conversion with UTF16ToWideHack<commit_after><|endoftext|>


<commit_before>/**********************************************************************
* File:        tessedit.cpp  (Formerly tessedit.c)
* Description: Main program for merge of tess and editor.
* Author:                  Ray Smith
* Created:                 Tue Jan 07 15:21:46 GMT 1992
*
* (C) Copyright 1992, Hewlett-Packard Ltd.
** 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.
*
**********************************************************************/

// #define USE_VLD //Uncomment for Visual Leak Detector.
#if (defined _MSC_VER && defined USE_VLD)
#include "mfcpch.h"
#include <vld.h>
#endif

// Include automatically generated configuration file if running autoconf
#ifdef HAVE_CONFIG_H
#include "config_auto.h"
#endif
#ifdef USING_GETTEXT
#include <libintl.h>
#include <locale.h>
#define _(x) gettext(x)
#else
#define _(x) (x)
#endif

#include "allheaders.h"
#include "baseapi.h"
#include "basedir.h"
#include "strngs.h"
#include "tesseractmain.h"
#include "tprintf.h"

/**********************************************************************
 *  main()
 *
 **********************************************************************/

int main(int argc, char **argv) {
#ifdef USING_GETTEXT
  setlocale (LC_ALL, "");
  bindtextdomain (PACKAGE, LOCALEDIR);
  textdomain (PACKAGE);
#endif
  if ((argc == 2 && strcmp(argv[1], "-v") == 0) ||
      (argc == 2 && strcmp(argv[1], "--version") == 0)) {
    char *versionStrP;

    fprintf(stderr, "tesseract %s\n", tesseract::TessBaseAPI::Version());

    versionStrP = getLeptonicaVersion();
    fprintf(stderr, " %s\n", versionStrP);
    lept_free(versionStrP);

    versionStrP = getImagelibVersions();
    fprintf(stderr, "  %s\n", versionStrP);
    lept_free(versionStrP);

    exit(0);
  }

  // Make the order of args a bit more forgiving than it used to be.
  const char* lang = "eng";
  const char* image = NULL;
  const char* output = NULL;
  bool noocr = false;
  bool list_langs = false;

  tesseract::PageSegMode pagesegmode = tesseract::PSM_AUTO;
  int arg = 1;
  while (arg < argc && (output == NULL || argv[arg][0] == '-')) {
    if (strcmp(argv[arg], "-l") == 0 && arg + 1 < argc) {
      lang = argv[arg + 1];
      ++arg;
    } else if (strcmp(argv[arg], "-psm") == 0 && arg + 1 < argc) {
      pagesegmode = static_cast<tesseract::PageSegMode>(atoi(argv[arg + 1]));
      ++arg;
    } else if (image == NULL) {
      image = argv[arg];
    } else if (output == NULL) {
      output = argv[arg];
    }
    ++arg;
  }

  if (argc == 2 && strcmp(argv[1], "--list-langs") == 0) {
    list_langs = true;
    noocr = true;
  }

  if (output == NULL && noocr == false) {
    fprintf(stderr, _("Usage:%s imagename outputbase [-l lang] "
                      "[-psm pagesegmode] [configfile...]\n\n"), argv[0]);
    fprintf(stderr,
            _("pagesegmode values are:\n"
              "0 = Orientation and script detection (OSD) only.\n"
              "1 = Automatic page segmentation with OSD.\n"
              "2 = Automatic page segmentation, but no OSD, or OCR\n"
              "3 = Fully automatic page segmentation, but no OSD. (Default)\n"
              "4 = Assume a single column of text of variable sizes.\n"
              "5 = Assume a single uniform block of vertically aligned text.\n"
              "6 = Assume a single uniform block of text.\n"
              "7 = Treat the image as a single text line.\n"
              "8 = Treat the image as a single word.\n"
              "9 = Treat the image as a single word in a circle.\n"
              "10 = Treat the image as a single character.\n"));
    fprintf(stderr, _("-l lang and/or -psm pagesegmode must occur before any"
                      "configfile.\n\n"));
    fprintf(stderr, _("Single options:\n"));
    fprintf(stderr, _("  -v --version: version info\n"));
    fprintf(stderr, _("  --list-langs: list available languages for tesseract "
                      "engine\n"));
    exit(1);
  }

  tesseract::TessBaseAPI api;

  STRING tessdata_dir;
  truncate_path(argv[0], &tessdata_dir);
  api.SetOutputName(output);
  int rc = api.Init(tessdata_dir.string(), lang, tesseract::OEM_DEFAULT,
                &(argv[arg]), argc - arg, NULL, NULL, false);

  if (rc) {
    fprintf(stderr, _("Could not initialize tesseract.\n"));
    exit(1);
  }

  if (list_langs) {
     GenericVector<STRING> languages;
     api.GetAvailableLanguagesAsVector(&languages);
     fprintf(stderr, _("List of available languages (%d):\n"),
             languages.size());
     for (int index = 0; index < languages.size(); ++index) {
       STRING& string = languages[index];
       fprintf(stderr, "%s\n", string.string());
     }
     api.End();
     exit(0);
  }

  // We have 2 possible sources of pagesegmode: a config file and
  // the command line. For backwards compatability reasons, the
  // default in tesseract is tesseract::PSM_SINGLE_BLOCK, but the
  // default for this program is tesseract::PSM_AUTO. We will let
  // the config file take priority, so the command-line default
  // can take priority over the tesseract default, so we use the
  // value from the command line only if the retrieved mode
  // is still tesseract::PSM_SINGLE_BLOCK, indicating no change
  // in any config file. Therefore the only way to force
  // tesseract::PSM_SINGLE_BLOCK is from the command line.
  // It would be simpler if we could set the value before Init,
  // but that doesn't work.
  if (api.GetPageSegMode() == tesseract::PSM_SINGLE_BLOCK)
    api.SetPageSegMode(pagesegmode);
  tprintf("Tesseract Open Source OCR Engine v%s with Leptonica\n",
           tesseract::TessBaseAPI::Version());

  FILE* fin = fopen(image, "rb");
  if (fin == NULL) {
    fprintf(stderr, _("Cannot open input file: %s\n"), image);
    exit(2);
  }
  fclose(fin);

  PIX   *pixs;
  if ((pixs = pixRead(image)) == NULL) {
    fprintf(stderr, _("Unsupported image type.\n"));
    exit(3);
  }
  pixDestroy(&pixs);

  STRING text_out;
  if (!api.ProcessPages(image, NULL, 0, &text_out)) {
    fprintf(stderr, _("Error during processing.\n"));
  }
  bool output_hocr = false;
  api.GetBoolVariable("tessedit_create_hocr", &output_hocr);
  bool output_box = false;
  api.GetBoolVariable("tessedit_create_boxfile", &output_box);
  STRING outfile = output;
  outfile += output_hocr ? ".html" : output_box ? ".box" : ".txt";
  FILE* fout = fopen(outfile.string(), "wb");
  if (fout == NULL) {
    fprintf(stderr, _("Cannot create output file %s\n"), outfile.string());
    exit(1);
  }
  fwrite(text_out.string(), 1, text_out.length(), fout);
  fclose(fout);

  return 0;                      // Normal exit
}

#ifdef _WIN32

char szAppName[] = "Tesseract";   //app name
int initialized = 0;

/**********************************************************************
* WinMain
*
* Main function for a windows program.
**********************************************************************/

int WINAPI WinMain(  //main for windows //command line
        HINSTANCE hInstance,
        HINSTANCE hPrevInstance,
        LPSTR lpszCmdLine,
        int nCmdShow) {
  WNDCLASS wc;
  HWND hwnd;
  MSG msg;

  char **argv;
  char *argsin[2];
  int argc;
  int exit_code;

  wc.style = CS_NOCLOSE | CS_OWNDC;
  wc.lpfnWndProc = (WNDPROC) WndProc;
  wc.cbClsExtra = 0;
  wc.cbWndExtra = 0;
  wc.hInstance = hInstance;
  wc.hIcon = NULL;         //LoadIcon (NULL, IDI_APPLICATION);
  wc.hCursor = NULL;       //LoadCursor (NULL, IDC_ARROW);
  wc.hbrBackground = (HBRUSH) (COLOR_WINDOW + 1);
  wc.lpszMenuName = NULL;
  wc.lpszClassName = szAppName;

  RegisterClass(&wc);

  hwnd = CreateWindow (szAppName, szAppName,
                       WS_OVERLAPPEDWINDOW | WS_DISABLED,
                       CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
                       CW_USEDEFAULT, HWND_DESKTOP, NULL, hInstance, NULL);

  argsin[0] = strdup (szAppName);
  argsin[1] = strdup (lpszCmdLine);
  /*allocate memory for the args. There can never be more than half*/
  /*the total number of characters in the arguments.*/
  argv = (char **)malloc(((strlen(argsin[0]) + strlen(argsin[1])) / 2 + 1) *
                         sizeof(char *));

  /*now construct argv as it should be for C.*/
  argc = parse_args (2, argsin, argv);

  //  ShowWindow (hwnd, nCmdShow);
  //  UpdateWindow (hwnd);

  if (initialized) {
    exit_code = main (argc, argv);
    free (argsin[0]);
    free (argsin[1]);
    free(argv);
    return exit_code;
  }
  while (GetMessage (&msg, NULL, 0, 0)) {
    TranslateMessage(&msg);
    DispatchMessage(&msg);
    if (initialized) {
      exit_code = main (argc, argv);
      break;
    }
    else
      exit_code = msg.wParam;
  }
  free (argsin[0]);
  free (argsin[1]);
  free(argv);
  return exit_code;
}

/**********************************************************************
* WndProc
*
* Function to respond to messages.
**********************************************************************/

LONG WINAPI WndProc(            //message handler
        HWND hwnd,              //window with message
        UINT msg,               //message typ
        WPARAM wParam,
        LPARAM lParam) {
  HDC hdc;

  if (msg == WM_CREATE) {
    //
    // Create a rendering context.
    //
    hdc = GetDC (hwnd);
    ReleaseDC(hwnd, hdc);
    initialized = 1;
    return 0;
  }
  return DefWindowProc (hwnd, msg, wParam, lParam);
}

/**********************************************************************
* parse_args
*
* Turn a list of args into a new list of args with each separate
* whitespace spaced string being an arg.
**********************************************************************/

int
parse_args (                     /*refine arg list */
        int argc,                /*no of input args */
        char *argv[],            /*input args */
        char *arglist[]          /*output args */
        ) {
  int argcount;            /*converted argc */
  char *testchar;          /*char in option string */
  int arg;                 /*current argument */

  argcount = 0;            /*no of options */
  for (arg = 0; arg < argc; arg++) {
    testchar = argv[arg]; /*start of arg */
    do {
      while (*testchar
             && (*testchar == ' ' || *testchar == '\n'
                 || *testchar == '\t'))
        testchar++; /*skip white space */
      if (*testchar) {
        /*new arg */
        arglist[argcount++] = testchar;
        /*skip to white space */
        for (testchar++; *testchar && *testchar != ' ' && *testchar != '\n' && *testchar != '\t'; testchar++) ;
        if (*testchar)
          *testchar++ = '\0'; /*turn to separate args */
      }
    }
    while (*testchar);
  }
  return argcount;         /*new number of args */
}
#endif
<commit_msg>Fix issue 808: Check for output file write permissions before performing lengthy OCR operation<commit_after>/**********************************************************************
* File:        tessedit.cpp  (Formerly tessedit.c)
* Description: Main program for merge of tess and editor.
* Author:                  Ray Smith
* Created:                 Tue Jan 07 15:21:46 GMT 1992
*
* (C) Copyright 1992, Hewlett-Packard Ltd.
** 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.
*
**********************************************************************/

// #define USE_VLD //Uncomment for Visual Leak Detector.
#if (defined _MSC_VER && defined USE_VLD)
#include "mfcpch.h"
#include <vld.h>
#endif

// Include automatically generated configuration file if running autoconf
#ifdef HAVE_CONFIG_H
#include "config_auto.h"
#endif
#ifdef USING_GETTEXT
#include <libintl.h>
#include <locale.h>
#define _(x) gettext(x)
#else
#define _(x) (x)
#endif

#include "allheaders.h"
#include "baseapi.h"
#include "basedir.h"
#include "strngs.h"
#include "tesseractmain.h"
#include "tprintf.h"

/**********************************************************************
 *  main()
 *
 **********************************************************************/

int main(int argc, char **argv) {
#ifdef USING_GETTEXT
  setlocale (LC_ALL, "");
  bindtextdomain (PACKAGE, LOCALEDIR);
  textdomain (PACKAGE);
#endif
  if ((argc == 2 && strcmp(argv[1], "-v") == 0) ||
      (argc == 2 && strcmp(argv[1], "--version") == 0)) {
    char *versionStrP;

    fprintf(stderr, "tesseract %s\n", tesseract::TessBaseAPI::Version());

    versionStrP = getLeptonicaVersion();
    fprintf(stderr, " %s\n", versionStrP);
    lept_free(versionStrP);

    versionStrP = getImagelibVersions();
    fprintf(stderr, "  %s\n", versionStrP);
    lept_free(versionStrP);

    exit(0);
  }

  // Make the order of args a bit more forgiving than it used to be.
  const char* lang = "eng";
  const char* image = NULL;
  const char* output = NULL;
  bool noocr = false;
  bool list_langs = false;

  tesseract::PageSegMode pagesegmode = tesseract::PSM_AUTO;
  int arg = 1;
  while (arg < argc && (output == NULL || argv[arg][0] == '-')) {
    if (strcmp(argv[arg], "-l") == 0 && arg + 1 < argc) {
      lang = argv[arg + 1];
      ++arg;
    } else if (strcmp(argv[arg], "-psm") == 0 && arg + 1 < argc) {
      pagesegmode = static_cast<tesseract::PageSegMode>(atoi(argv[arg + 1]));
      ++arg;
    } else if (image == NULL) {
      image = argv[arg];
    } else if (output == NULL) {
      output = argv[arg];
    }
    ++arg;
  }

  if (argc == 2 && strcmp(argv[1], "--list-langs") == 0) {
    list_langs = true;
    noocr = true;
  }

  if (output == NULL && noocr == false) {
    fprintf(stderr, _("Usage:%s imagename outputbase [-l lang] "
                      "[-psm pagesegmode] [configfile...]\n\n"), argv[0]);
    fprintf(stderr,
            _("pagesegmode values are:\n"
              "0 = Orientation and script detection (OSD) only.\n"
              "1 = Automatic page segmentation with OSD.\n"
              "2 = Automatic page segmentation, but no OSD, or OCR\n"
              "3 = Fully automatic page segmentation, but no OSD. (Default)\n"
              "4 = Assume a single column of text of variable sizes.\n"
              "5 = Assume a single uniform block of vertically aligned text.\n"
              "6 = Assume a single uniform block of text.\n"
              "7 = Treat the image as a single text line.\n"
              "8 = Treat the image as a single word.\n"
              "9 = Treat the image as a single word in a circle.\n"
              "10 = Treat the image as a single character.\n"));
    fprintf(stderr, _("-l lang and/or -psm pagesegmode must occur before any"
                      "configfile.\n\n"));
    fprintf(stderr, _("Single options:\n"));
    fprintf(stderr, _("  -v --version: version info\n"));
    fprintf(stderr, _("  --list-langs: list available languages for tesseract "
                      "engine\n"));
    exit(1);
  }

  tesseract::TessBaseAPI api;

  STRING tessdata_dir;
  truncate_path(argv[0], &tessdata_dir);
  api.SetOutputName(output);
  int rc = api.Init(tessdata_dir.string(), lang, tesseract::OEM_DEFAULT,
                &(argv[arg]), argc - arg, NULL, NULL, false);

  if (rc) {
    fprintf(stderr, _("Could not initialize tesseract.\n"));
    exit(1);
  }

  if (list_langs) {
     GenericVector<STRING> languages;
     api.GetAvailableLanguagesAsVector(&languages);
     fprintf(stderr, _("List of available languages (%d):\n"),
             languages.size());
     for (int index = 0; index < languages.size(); ++index) {
       STRING& string = languages[index];
       fprintf(stderr, "%s\n", string.string());
     }
     api.End();
     exit(0);
  }

  // We have 2 possible sources of pagesegmode: a config file and
  // the command line. For backwards compatability reasons, the
  // default in tesseract is tesseract::PSM_SINGLE_BLOCK, but the
  // default for this program is tesseract::PSM_AUTO. We will let
  // the config file take priority, so the command-line default
  // can take priority over the tesseract default, so we use the
  // value from the command line only if the retrieved mode
  // is still tesseract::PSM_SINGLE_BLOCK, indicating no change
  // in any config file. Therefore the only way to force
  // tesseract::PSM_SINGLE_BLOCK is from the command line.
  // It would be simpler if we could set the value before Init,
  // but that doesn't work.
  if (api.GetPageSegMode() == tesseract::PSM_SINGLE_BLOCK)
    api.SetPageSegMode(pagesegmode);
  tprintf("Tesseract Open Source OCR Engine v%s with Leptonica\n",
           tesseract::TessBaseAPI::Version());

  FILE* fin = fopen(image, "rb");
  if (fin == NULL) {
    fprintf(stderr, _("Cannot open input file: %s\n"), image);
    exit(2);
  }
  fclose(fin);

  PIX   *pixs;
  if ((pixs = pixRead(image)) == NULL) {
    fprintf(stderr, _("Unsupported image type.\n"));
    exit(3);
  }
  pixDestroy(&pixs);

  bool output_hocr = false;
  api.GetBoolVariable("tessedit_create_hocr", &output_hocr);
  bool output_box = false;
  api.GetBoolVariable("tessedit_create_boxfile", &output_box);
  STRING outfile = output;
  outfile += output_hocr ? ".html" : output_box ? ".box" : ".txt";
  FILE* fout = fopen(outfile.string(), "wb");
  if (fout == NULL) {
    fprintf(stderr, _("Cannot create output file %s\n"), outfile.string());
    exit(1);
  }

  STRING text_out;
  if (!api.ProcessPages(image, NULL, 0, &text_out)) {
    fprintf(stderr, _("Error during processing.\n"));
  }

  fwrite(text_out.string(), 1, text_out.length(), fout);
  fclose(fout);

  return 0;                      // Normal exit
}

#ifdef _WIN32

char szAppName[] = "Tesseract";   //app name
int initialized = 0;

/**********************************************************************
* WinMain
*
* Main function for a windows program.
**********************************************************************/

int WINAPI WinMain(  //main for windows //command line
        HINSTANCE hInstance,
        HINSTANCE hPrevInstance,
        LPSTR lpszCmdLine,
        int nCmdShow) {
  WNDCLASS wc;
  HWND hwnd;
  MSG msg;

  char **argv;
  char *argsin[2];
  int argc;
  int exit_code;

  wc.style = CS_NOCLOSE | CS_OWNDC;
  wc.lpfnWndProc = (WNDPROC) WndProc;
  wc.cbClsExtra = 0;
  wc.cbWndExtra = 0;
  wc.hInstance = hInstance;
  wc.hIcon = NULL;         //LoadIcon (NULL, IDI_APPLICATION);
  wc.hCursor = NULL;       //LoadCursor (NULL, IDC_ARROW);
  wc.hbrBackground = (HBRUSH) (COLOR_WINDOW + 1);
  wc.lpszMenuName = NULL;
  wc.lpszClassName = szAppName;

  RegisterClass(&wc);

  hwnd = CreateWindow (szAppName, szAppName,
                       WS_OVERLAPPEDWINDOW | WS_DISABLED,
                       CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
                       CW_USEDEFAULT, HWND_DESKTOP, NULL, hInstance, NULL);

  argsin[0] = strdup (szAppName);
  argsin[1] = strdup (lpszCmdLine);
  /*allocate memory for the args. There can never be more than half*/
  /*the total number of characters in the arguments.*/
  argv = (char **)malloc(((strlen(argsin[0]) + strlen(argsin[1])) / 2 + 1) *
                         sizeof(char *));

  /*now construct argv as it should be for C.*/
  argc = parse_args (2, argsin, argv);

  //  ShowWindow (hwnd, nCmdShow);
  //  UpdateWindow (hwnd);

  if (initialized) {
    exit_code = main (argc, argv);
    free (argsin[0]);
    free (argsin[1]);
    free(argv);
    return exit_code;
  }
  while (GetMessage (&msg, NULL, 0, 0)) {
    TranslateMessage(&msg);
    DispatchMessage(&msg);
    if (initialized) {
      exit_code = main (argc, argv);
      break;
    }
    else
      exit_code = msg.wParam;
  }
  free (argsin[0]);
  free (argsin[1]);
  free(argv);
  return exit_code;
}

/**********************************************************************
* WndProc
*
* Function to respond to messages.
**********************************************************************/

LONG WINAPI WndProc(            //message handler
        HWND hwnd,              //window with message
        UINT msg,               //message typ
        WPARAM wParam,
        LPARAM lParam) {
  HDC hdc;

  if (msg == WM_CREATE) {
    //
    // Create a rendering context.
    //
    hdc = GetDC (hwnd);
    ReleaseDC(hwnd, hdc);
    initialized = 1;
    return 0;
  }
  return DefWindowProc (hwnd, msg, wParam, lParam);
}

/**********************************************************************
* parse_args
*
* Turn a list of args into a new list of args with each separate
* whitespace spaced string being an arg.
**********************************************************************/

int
parse_args (                     /*refine arg list */
        int argc,                /*no of input args */
        char *argv[],            /*input args */
        char *arglist[]          /*output args */
        ) {
  int argcount;            /*converted argc */
  char *testchar;          /*char in option string */
  int arg;                 /*current argument */

  argcount = 0;            /*no of options */
  for (arg = 0; arg < argc; arg++) {
    testchar = argv[arg]; /*start of arg */
    do {
      while (*testchar
             && (*testchar == ' ' || *testchar == '\n'
                 || *testchar == '\t'))
        testchar++; /*skip white space */
      if (*testchar) {
        /*new arg */
        arglist[argcount++] = testchar;
        /*skip to white space */
        for (testchar++; *testchar && *testchar != ' ' && *testchar != '\n' && *testchar != '\t'; testchar++) ;
        if (*testchar)
          *testchar++ = '\0'; /*turn to separate args */
      }
    }
    while (*testchar);
  }
  return argcount;         /*new number of args */
}
#endif
<|endoftext|>


<commit_before>/*

Copyright (c) 2007, Arvid Norberg
All rights reserved.

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

    * Redistributions of source code must retain the above copyright
      notice, this list of conditions and the following disclaimer.
    * Redistributions in binary form must reproduce the above copyright
      notice, this list of conditions and the following disclaimer in
      the documentation and/or other materials provided with the distribution.
    * Neither the name of the author nor the names of its
      contributors may be used to endorse or promote products derived
      from this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER 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.

*/

#ifndef TORRENT_PROXY_BASE_HPP_INCLUDED
#define TORRENT_PROXY_BASE_HPP_INCLUDED

#include "libtorrent/io.hpp"
#include "libtorrent/socket.hpp"
#include <boost/bind.hpp>
#include <boost/lexical_cast.hpp>
#include <boost/function.hpp>
#include <asio/read.hpp>
#include <asio/write.hpp>

namespace libtorrent {

class proxy_base : boost::noncopyable
{
public:

	typedef stream_socket::lowest_layer_type lowest_layer_type;
	typedef stream_socket::endpoint_type endpoint_type;
	typedef stream_socket::protocol_type protocol_type;

	explicit proxy_base(asio::io_service& io_service)
		: m_sock(io_service)
		, m_resolver(io_service)
	{}

	void set_proxy(std::string hostname, int port)
	{
		m_hostname = hostname;
		m_port = port;
	}

	template <class Mutable_Buffers, class Handler>
	void async_read_some(Mutable_Buffers const& buffers, Handler const& handler)
	{
		m_sock.async_read_some(buffers, handler);
	}

	template <class Mutable_Buffers>
	std::size_t read_some(Mutable_Buffers const& buffers, asio::error_code& ec)
	{
		return m_sock.read_some(buffers, ec);
	}

	template <class Mutable_Buffers>
	std::size_t read_some(Mutable_Buffers const& buffers)
	{
		return m_sock.read_some(buffers);
	}

	template <class IO_Control_Command>
	void io_control(IO_Control_Command& ioc)
	{
		m_sock.io_control(ioc);
	}

	template <class IO_Control_Command>
	void io_control(IO_Control_Command& ioc, asio::error_code& ec)
	{
		m_sock.io_control(ioc, ec);
	}

	template <class Const_Buffers, class Handler>
	void async_write_some(Const_Buffers const& buffers, Handler const& handler)
	{
		m_sock.async_write_some(buffers, handler);
	}

	void bind(endpoint_type const& endpoint)
	{
		m_sock.bind(endpoint);
	}

	template <class Error_Handler>
	void bind(endpoint_type const& endpoint, Error_Handler const& error_handler)
	{
		m_sock.bind(endpoint, error_handler);
	}

	void open(protocol_type const& p)
	{
		m_sock.open(p);
	}

	template <class Error_Handler>
	void open(protocol_type const& p, Error_Handler const& error_handler)
	{
		m_sock.open(p, error_handler);
	}

	void close()
	{
		m_remote_endpoint = endpoint_type();
		m_sock.close();
	}

	template <class Error_Handler>
	void close(Error_Handler const& error_handler)
	{
		m_sock.close(error_handler);
	}

	endpoint_type remote_endpoint()
	{
		return m_remote_endpoint;
	}

	template <class Error_Handler>
	endpoint_type remote_endpoint(Error_Handler const& error_handler)
	{
		return m_remote_endpoint;
	}

	endpoint_type local_endpoint()
	{
		return m_sock.local_endpoint();
	}

	template <class Error_Handler>
	endpoint_type local_endpoint(Error_Handler const& error_handler)
	{
		return m_sock.local_endpoint(error_handler);
	}

	asio::io_service& io_service()
	{
		return m_sock.io_service();
	}

	lowest_layer_type& lowest_layer()
	{
		return m_sock.lowest_layer();
	}

protected:

	stream_socket m_sock;
	std::string m_hostname;
	int m_port;

	endpoint_type m_remote_endpoint;

	tcp::resolver m_resolver;
};

}

#endif

<commit_msg>cleaned up unnecessary template functions<commit_after>/*

Copyright (c) 2007, Arvid Norberg
All rights reserved.

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

    * Redistributions of source code must retain the above copyright
      notice, this list of conditions and the following disclaimer.
    * Redistributions in binary form must reproduce the above copyright
      notice, this list of conditions and the following disclaimer in
      the documentation and/or other materials provided with the distribution.
    * Neither the name of the author nor the names of its
      contributors may be used to endorse or promote products derived
      from this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER 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.

*/

#ifndef TORRENT_PROXY_BASE_HPP_INCLUDED
#define TORRENT_PROXY_BASE_HPP_INCLUDED

#include "libtorrent/io.hpp"
#include "libtorrent/socket.hpp"
#include <boost/bind.hpp>
#include <boost/lexical_cast.hpp>
#include <boost/function.hpp>
#include <asio/read.hpp>
#include <asio/write.hpp>

namespace libtorrent {

class proxy_base : boost::noncopyable
{
public:

	typedef stream_socket::lowest_layer_type lowest_layer_type;
	typedef stream_socket::endpoint_type endpoint_type;
	typedef stream_socket::protocol_type protocol_type;

	explicit proxy_base(asio::io_service& io_service)
		: m_sock(io_service)
		, m_resolver(io_service)
	{}

	void set_proxy(std::string hostname, int port)
	{
		m_hostname = hostname;
		m_port = port;
	}

	template <class Mutable_Buffers, class Handler>
	void async_read_some(Mutable_Buffers const& buffers, Handler const& handler)
	{
		m_sock.async_read_some(buffers, handler);
	}

	template <class Mutable_Buffers>
	std::size_t read_some(Mutable_Buffers const& buffers, asio::error_code& ec)
	{
		return m_sock.read_some(buffers, ec);
	}

	template <class Mutable_Buffers>
	std::size_t read_some(Mutable_Buffers const& buffers)
	{
		return m_sock.read_some(buffers);
	}

	template <class IO_Control_Command>
	void io_control(IO_Control_Command& ioc)
	{
		m_sock.io_control(ioc);
	}

	template <class IO_Control_Command>
	void io_control(IO_Control_Command& ioc, asio::error_code& ec)
	{
		m_sock.io_control(ioc, ec);
	}

	template <class Const_Buffers, class Handler>
	void async_write_some(Const_Buffers const& buffers, Handler const& handler)
	{
		m_sock.async_write_some(buffers, handler);
	}

	void bind(endpoint_type const& endpoint)
	{
		m_sock.bind(endpoint);
	}

	void bind(endpoint_type const& endpoint, asio::error_code& ec)
	{
		m_sock.bind(endpoint, ec);
	}

	void open(protocol_type const& p)
	{
		m_sock.open(p);
	}

	void open(protocol_type const& p, asio::error_code& ec)
	{
		m_sock.open(p, ec);
	}

	void close()
	{
		m_remote_endpoint = endpoint_type();
		m_sock.close();
	}

	void close(asio::error_code& ec)
	{
		m_sock.close(ec);
	}

	endpoint_type remote_endpoint()
	{
		return m_remote_endpoint;
	}

	endpoint_type remote_endpoint(asio::error_code& ec)
	{
		return m_remote_endpoint;
	}

	endpoint_type local_endpoint()
	{
		return m_sock.local_endpoint();
	}

	endpoint_type local_endpoint(asio::error_code& ec)
	{
		return m_sock.local_endpoint(ec);
	}

	asio::io_service& io_service()
	{
		return m_sock.io_service();
	}

	lowest_layer_type& lowest_layer()
	{
		return m_sock.lowest_layer();
	}

protected:

	stream_socket m_sock;
	std::string m_hostname;
	int m_port;

	endpoint_type m_remote_endpoint;

	tcp::resolver m_resolver;
};

}

#endif

<|endoftext|>


<commit_before>/*

Copyright (c) 2007, Arvid Norberg
All rights reserved.

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

    * Redistributions of source code must retain the above copyright
      notice, this list of conditions and the following disclaimer.
    * Redistributions in binary form must reproduce the above copyright
      notice, this list of conditions and the following disclaimer in
      the documentation and/or other materials provided with the distribution.
    * Neither the name of the author nor the names of its
      contributors may be used to endorse or promote products derived
      from this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER 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.

*/

#ifndef TORRENT_UDP_SOCKET_HPP_INCLUDED
#define TORRENT_UDP_SOCKET_HPP_INCLUDED

#include "libtorrent/socket.hpp"
#include "libtorrent/io_service.hpp"
#include "libtorrent/error_code.hpp"
#include "libtorrent/session_settings.hpp"
#include "libtorrent/buffer.hpp"
#include "libtorrent/thread.hpp"
#include "libtorrent/deadline_timer.hpp"

#include <vector>
#include <boost/function/function4.hpp>

namespace libtorrent
{
	class connection_queue;

	class udp_socket
	{
	public:
		typedef boost::function<void(error_code const& ec
			, udp::endpoint const&, char const* buf, int size)> callback_t;

		udp_socket(io_service& ios, callback_t const& c, connection_queue& cc);
		~udp_socket();

		bool is_open() const
		{
			return m_ipv4_sock.is_open()
#if TORRENT_USE_IPV6
				|| m_ipv6_sock.is_open()
#endif
				;
		}
		io_service& get_io_service() { return m_ipv4_sock.get_io_service(); }

		void send(udp::endpoint const& ep, char const* p, int len, error_code& ec);
		void bind(udp::endpoint const& ep, error_code& ec);
		void bind(int port);
		void close();
		int local_port() const { return m_bind_port; }

		void set_proxy_settings(proxy_settings const& ps);
		proxy_settings const& get_proxy_settings() { return m_proxy_settings; }

		bool is_closed() const { return m_abort; }
		tcp::endpoint local_endpoint() const
		{
			udp::endpoint ep = m_ipv4_sock.local_endpoint();
			return tcp::endpoint(ep.address(), ep.port());
		}

	protected:

		struct queued_packet
		{
			udp::endpoint ep;
			buffer buf;
		};

	private:

		callback_t m_callback;

		void on_read(udp::socket* sock, error_code const& e, std::size_t bytes_transferred);
		void on_name_lookup(error_code const& e, tcp::resolver::iterator i);
		void on_timeout();
		void on_connect(int ticket);
		void on_connected(error_code const& ec);
		void handshake1(error_code const& e);
		void handshake2(error_code const& e);
		void handshake3(error_code const& e);
		void handshake4(error_code const& e);
		void socks_forward_udp(mutex::scoped_lock& l);
		void connect1(error_code const& e);
		void connect2(error_code const& e);

		void wrap(udp::endpoint const& ep, char const* p, int len, error_code& ec);
		void unwrap(error_code const& e, char const* buf, int size);

		mutable mutex m_mutex;

		udp::socket m_ipv4_sock;
		udp::endpoint m_v4_ep;
		char m_v4_buf[1600];

#if TORRENT_USE_IPV6
		udp::socket m_ipv6_sock;
		udp::endpoint m_v6_ep;
		char m_v6_buf[1600];
#endif

		int m_bind_port;
		char m_outstanding;

		tcp::socket m_socks5_sock;
		int m_connection_ticket;
		proxy_settings m_proxy_settings;
		connection_queue& m_cc;
		tcp::resolver m_resolver;
		char m_tmp_buf[100];
		bool m_queue_packets;
		bool m_tunnel_packets;
		bool m_abort;
		udp::endpoint m_proxy_addr;
		// while we're connecting to the proxy
		// we have to queue the packets, we'll flush
		// them once we're connected
		std::list<queued_packet> m_queue;
#ifdef TORRENT_DEBUG
		bool m_started;
		int m_magic;
		int m_outstanding_when_aborted;
#endif
	};

	struct rate_limited_udp_socket : public udp_socket
	{
		rate_limited_udp_socket(io_service& ios, callback_t const& c, connection_queue& cc);
		void set_rate_limit(int limit) { m_rate_limit = limit; }
		bool can_send() const { return int(m_queue.size()) >= m_queue_size_limit; }
		bool send(udp::endpoint const& ep, char const* p, int len, error_code& ec, int flags = 0);
		void close();

	private:
		void on_tick(error_code const& e);

		deadline_timer m_timer;
		int m_queue_size_limit;
		int m_rate_limit;
		int m_quota;
		ptime m_last_tick;
		std::list<queued_packet> m_queue;
	};
}

#endif

<commit_msg>ignore failures in when asking for local_endpoint<commit_after>/*

Copyright (c) 2007, Arvid Norberg
All rights reserved.

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

    * Redistributions of source code must retain the above copyright
      notice, this list of conditions and the following disclaimer.
    * Redistributions in binary form must reproduce the above copyright
      notice, this list of conditions and the following disclaimer in
      the documentation and/or other materials provided with the distribution.
    * Neither the name of the author nor the names of its
      contributors may be used to endorse or promote products derived
      from this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER 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.

*/

#ifndef TORRENT_UDP_SOCKET_HPP_INCLUDED
#define TORRENT_UDP_SOCKET_HPP_INCLUDED

#include "libtorrent/socket.hpp"
#include "libtorrent/io_service.hpp"
#include "libtorrent/error_code.hpp"
#include "libtorrent/session_settings.hpp"
#include "libtorrent/buffer.hpp"
#include "libtorrent/thread.hpp"
#include "libtorrent/deadline_timer.hpp"

#include <vector>
#include <boost/function/function4.hpp>

namespace libtorrent
{
	class connection_queue;

	class udp_socket
	{
	public:
		typedef boost::function<void(error_code const& ec
			, udp::endpoint const&, char const* buf, int size)> callback_t;

		udp_socket(io_service& ios, callback_t const& c, connection_queue& cc);
		~udp_socket();

		bool is_open() const
		{
			return m_ipv4_sock.is_open()
#if TORRENT_USE_IPV6
				|| m_ipv6_sock.is_open()
#endif
				;
		}
		io_service& get_io_service() { return m_ipv4_sock.get_io_service(); }

		void send(udp::endpoint const& ep, char const* p, int len, error_code& ec);
		void bind(udp::endpoint const& ep, error_code& ec);
		void bind(int port);
		void close();
		int local_port() const { return m_bind_port; }

		void set_proxy_settings(proxy_settings const& ps);
		proxy_settings const& get_proxy_settings() { return m_proxy_settings; }

		bool is_closed() const { return m_abort; }
		tcp::endpoint local_endpoint() const
		{
			error_code ec;
			udp::endpoint ep = m_ipv4_sock.local_endpoint(ec);
			return tcp::endpoint(ep.address(), ep.port());
		}

	protected:

		struct queued_packet
		{
			udp::endpoint ep;
			buffer buf;
		};

	private:

		callback_t m_callback;

		void on_read(udp::socket* sock, error_code const& e, std::size_t bytes_transferred);
		void on_name_lookup(error_code const& e, tcp::resolver::iterator i);
		void on_timeout();
		void on_connect(int ticket);
		void on_connected(error_code const& ec);
		void handshake1(error_code const& e);
		void handshake2(error_code const& e);
		void handshake3(error_code const& e);
		void handshake4(error_code const& e);
		void socks_forward_udp(mutex::scoped_lock& l);
		void connect1(error_code const& e);
		void connect2(error_code const& e);

		void wrap(udp::endpoint const& ep, char const* p, int len, error_code& ec);
		void unwrap(error_code const& e, char const* buf, int size);

		mutable mutex m_mutex;

		udp::socket m_ipv4_sock;
		udp::endpoint m_v4_ep;
		char m_v4_buf[1600];

#if TORRENT_USE_IPV6
		udp::socket m_ipv6_sock;
		udp::endpoint m_v6_ep;
		char m_v6_buf[1600];
#endif

		int m_bind_port;
		char m_outstanding;

		tcp::socket m_socks5_sock;
		int m_connection_ticket;
		proxy_settings m_proxy_settings;
		connection_queue& m_cc;
		tcp::resolver m_resolver;
		char m_tmp_buf[100];
		bool m_queue_packets;
		bool m_tunnel_packets;
		bool m_abort;
		udp::endpoint m_proxy_addr;
		// while we're connecting to the proxy
		// we have to queue the packets, we'll flush
		// them once we're connected
		std::list<queued_packet> m_queue;
#ifdef TORRENT_DEBUG
		bool m_started;
		int m_magic;
		int m_outstanding_when_aborted;
#endif
	};

	struct rate_limited_udp_socket : public udp_socket
	{
		rate_limited_udp_socket(io_service& ios, callback_t const& c, connection_queue& cc);
		void set_rate_limit(int limit) { m_rate_limit = limit; }
		bool can_send() const { return int(m_queue.size()) >= m_queue_size_limit; }
		bool send(udp::endpoint const& ep, char const* p, int len, error_code& ec, int flags = 0);
		void close();

	private:
		void on_tick(error_code const& e);

		deadline_timer m_timer;
		int m_queue_size_limit;
		int m_rate_limit;
		int m_quota;
		ptime m_last_tick;
		std::list<queued_packet> m_queue;
	};
}

#endif

<|endoftext|>