<commit_before>// Copyright (c) 2006-2008 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 "chrome/app/chrome_dll_resource.h"
#include "chrome/browser/find_bar_win.h"
#include "chrome/test/automation/browser_proxy.h"
#include "chrome/test/automation/tab_proxy.h"
#include "chrome/test/automation/window_proxy.h"
#include "chrome/test/ui/ui_test.h"
#include "net/url_request/url_request_unittest.h"

class FindInPageControllerTest : public UITest {
 public:
  FindInPageControllerTest() {
    show_window_ = true;
  }
};

const std::wstring kFramePage = L"files/find_in_page/frames.html";
const std::wstring kUserSelectPage = L"files/find_in_page/user-select.html";
const std::wstring kCrashPage = L"files/find_in_page/crash_1341577.html";
const std::wstring kTooFewMatchesPage = L"files/find_in_page/bug_1155639.html";

// This test loads a page with frames and starts FindInPage requests
TEST_F(FindInPageControllerTest, FindInPageFrames) {
  TestServer server(L"chrome/test/data");

  // First we navigate to our frames page.
  GURL url = server.TestServerPageW(kFramePage);
  scoped_ptr<TabProxy> tab(GetActiveTab());
  ASSERT_TRUE(tab->NavigateToURL(url));
  WaitUntilTabCount(1);

  // Try incremental search (mimicking user typing in).
  EXPECT_EQ(18, tab->FindInPage(L"g",       FWD, IGNORE_CASE, false));
  EXPECT_EQ(11, tab->FindInPage(L"go",      FWD, IGNORE_CASE, false));
  EXPECT_EQ(04, tab->FindInPage(L"goo",     FWD, IGNORE_CASE, false));
  EXPECT_EQ(03, tab->FindInPage(L"goog",    FWD, IGNORE_CASE, false));
  EXPECT_EQ(02, tab->FindInPage(L"googl",   FWD, IGNORE_CASE, false));
  EXPECT_EQ(01, tab->FindInPage(L"google",  FWD, IGNORE_CASE, false));
  EXPECT_EQ(00, tab->FindInPage(L"google!", FWD, IGNORE_CASE, false));

  // Negative test (no matches should be found).
  EXPECT_EQ(0, tab->FindInPage(L"Non-existing string", FWD, IGNORE_CASE,
                               false));

  // 'horse' only exists in the three right frames.
  EXPECT_EQ(3, tab->FindInPage(L"horse", FWD, IGNORE_CASE, false));

  // 'cat' only exists in the first frame.
  EXPECT_EQ(1, tab->FindInPage(L"cat", FWD, IGNORE_CASE, false));

  // Try searching again, should still come up with 1 match.
  EXPECT_EQ(1, tab->FindInPage(L"cat", FWD, IGNORE_CASE, false));

  // Try searching backwards, ignoring case, should still come up with 1 match.
  EXPECT_EQ(1, tab->FindInPage(L"CAT", BACK, IGNORE_CASE, false));

  // Try case sensitive, should NOT find it.
  EXPECT_EQ(0, tab->FindInPage(L"CAT", FWD, CASE_SENSITIVE, false));

  // Try again case sensitive, but this time with right case.
  EXPECT_EQ(1, tab->FindInPage(L"dog", FWD, CASE_SENSITIVE, false));

  // Try non-Latin characters ('Hreggvidur' with 'eth' for 'd' in left frame).
  EXPECT_EQ(1, tab->FindInPage(L"Hreggvi\u00F0ur", FWD, IGNORE_CASE, false));
  EXPECT_EQ(1, tab->FindInPage(L"Hreggvi\u00F0ur", FWD, CASE_SENSITIVE, false));
  EXPECT_EQ(0, tab->FindInPage(L"hreggvi\u00F0ur", FWD, CASE_SENSITIVE, false));
}

// Load a page with no selectable text and make sure we don't crash.
TEST_F(FindInPageControllerTest, FindUnSelectableText) {
  TestServer server(L"chrome/test/data");

  GURL url = server.TestServerPageW(kUserSelectPage);
  scoped_ptr<TabProxy> tab(GetActiveTab());
  ASSERT_TRUE(tab->NavigateToURL(url));
  WaitUntilTabCount(1);

  EXPECT_EQ(0, tab->FindInPage(L"text", FWD, IGNORE_CASE, false));
  EXPECT_EQ(0, tab->FindInPage(L"Non-existing string", FWD, IGNORE_CASE,
                               false));
}

// Try to reproduce the crash seen in issue 1341577.
TEST_F(FindInPageControllerTest, FindCrash_Issue1341577) {
  TestServer server(L"chrome/test/data");

  GURL url = server.TestServerPageW(kCrashPage);
  scoped_ptr<TabProxy> tab(GetActiveTab());
  ASSERT_TRUE(tab->NavigateToURL(url));
  WaitUntilTabCount(1);

  // This would crash the tab. These must be the first two find requests issued
  // against the frame, otherwise an active frame pointer is set and it wont
  // produce the crash.
  EXPECT_EQ(1, tab->FindInPage(L"\u0D4C", FWD, IGNORE_CASE, false));
  // FindNext returns -1 for match count because it doesn't bother with
  // recounting the number of matches. We don't care about the match count
  // anyway in this case, we just want to make sure it doesn't crash.
  EXPECT_EQ(-1, tab->FindInPage(L"\u0D4C", FWD, IGNORE_CASE, true));

  // This should work fine.
  EXPECT_EQ(1, tab->FindInPage(L"\u0D24\u0D46", FWD, IGNORE_CASE, false));
  EXPECT_EQ(0, tab->FindInPage(L"nostring", FWD, IGNORE_CASE, false));
}

// Test to make sure Find does the right thing when restarting from a timeout.
// We used to have a problem where we'd stop finding matches when all of the
// following conditions were true:
// 1) The page has a lot of text to search.
// 2) The page contains more than one match.
// 3) It takes longer than the time-slice given to each Find operation (100
//    ms) to find one or more of those matches (so Find times out and has to try
//    again from where it left off).
TEST_F(FindInPageControllerTest, FindEnoughMatches_Issue1155639) {
  TestServer server(L"chrome/test/data");

  GURL url = server.TestServerPageW(kTooFewMatchesPage);
  scoped_ptr<TabProxy> tab(GetActiveTab());
  ASSERT_TRUE(tab->NavigateToURL(url));
  WaitUntilTabCount(1);

  // This string appears 5 times at the bottom of a long page. If Find restarts
  // properly after a timeout, it will find 5 matches, not just 1.
  EXPECT_EQ(5, tab->FindInPage(L"008.xml", FWD, IGNORE_CASE, false));
}

// The find window should not change its location just because we open and close
// a new tab.
TEST_F(FindInPageControllerTest, FindMovesOnTabClose_Issue1343052) {
  fprintf(stderr, "Starting FindMovesOnTabClose_Issue1343052\n");
  TestServer server(L"chrome/test/data");

  fprintf(stderr, "TestServerPageW\n");
  GURL url = server.TestServerPageW(kFramePage);
  fprintf(stderr, "GetActiveTab A\n");
  scoped_ptr<TabProxy> tabA(GetActiveTab());
  fprintf(stderr, "Navigate A\n");
  ASSERT_TRUE(tabA->NavigateToURL(url));
  fprintf(stderr, "WaitUntilTabCount(1) for A\n");
  WaitUntilTabCount(1);

  fprintf(stderr, "GetBrowserWindow(0)\n");
  scoped_ptr<BrowserProxy> browser(automation()->GetBrowserWindow(0));
  ASSERT_TRUE(browser.get() != NULL);

  // Toggle the bookmark bar state.
  fprintf(stderr, "ApplyAccelerator bookmark bar\n");
  browser->ApplyAccelerator(IDC_SHOW_BOOKMARKS_BAR);
  fprintf(stderr, "WaitForBookmarkVisibility\n");
  EXPECT_TRUE(WaitForBookmarkBarVisibilityChange(browser.get(), true));

  // Open the Find window and wait for it to animate.
  fprintf(stderr, "OpenFindInPage in A\n");
  EXPECT_TRUE(tabA->OpenFindInPage());
  fprintf(stderr, "WaitForWindowFullyVisible in A\n");
  EXPECT_TRUE(WaitForFindWindowFullyVisible(tabA.get()));

  // Find its location.
  int x = -1, y = -1;
  fprintf(stderr, "GetFindWindowLocation in A\n");
  EXPECT_TRUE(tabA->GetFindWindowLocation(&x, &y));

  // Open another tab (tab B).
  fprintf(stderr, "AppendTab B\n");
  EXPECT_TRUE(browser->AppendTab(url));
  fprintf(stderr, "GetActiveTab B\n");
  scoped_ptr<TabProxy> tabB(GetActiveTab());

  // Close tab B.
  fprintf(stderr, "Tab Close B\n");
  EXPECT_TRUE(tabB->Close(true));

  // See if the Find window has moved.
  int new_x = -1, new_y = -1;
  fprintf(stderr, "GetFindWindowLocation in A\n");
  EXPECT_TRUE(tabA->GetFindWindowLocation(&new_x, &new_y));

  EXPECT_EQ(x, new_x);
  EXPECT_EQ(y, new_y);

  // Now reset the bookmarks bar state and try the same again.
  fprintf(stderr, "ApplyAccelerator BookmarksBar\n");
  browser->ApplyAccelerator(IDC_SHOW_BOOKMARKS_BAR);
  fprintf(stderr, "WaitForBookmarkBarVisibilityChange\n");
  EXPECT_TRUE(WaitForBookmarkBarVisibilityChange(browser.get(), false));

  // Bookmark bar has moved, reset our coordinates.
  fprintf(stderr, "GetFindWindowLocation again\n");
  EXPECT_TRUE(tabA->GetFindWindowLocation(&x, &y));

  // Open another tab (tab C).
  fprintf(stderr, "Append tab C\n");
  EXPECT_TRUE(browser->AppendTab(url));
  fprintf(stderr, "GetActiveTab C\n");
  scoped_ptr<TabProxy> tabC(GetActiveTab());

  // Close it.
  fprintf(stderr, "Close tab C\n");
  EXPECT_TRUE(tabC->Close(true));

  // See if the Find window has moved.
  fprintf(stderr, "GetFindWindowLocation yet again\n");
  EXPECT_TRUE(tabA->GetFindWindowLocation(&new_x, &new_y));

  EXPECT_EQ(x, new_x);
  EXPECT_EQ(y, new_y);
  fprintf(stderr, "Done!\n");
}
<commit_msg>Fix include path from last checkin. Review URL: http://codereview.chromium.org/7815<commit_after>// Copyright (c) 2006-2008 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 "chrome/app/chrome_dll_resource.h"
#include "chrome/browser/views/find_bar_win.h"
#include "chrome/test/automation/browser_proxy.h"
#include "chrome/test/automation/tab_proxy.h"
#include "chrome/test/automation/window_proxy.h"
#include "chrome/test/ui/ui_test.h"
#include "net/url_request/url_request_unittest.h"

class FindInPageControllerTest : public UITest {
 public:
  FindInPageControllerTest() {
    show_window_ = true;
  }
};

const std::wstring kFramePage = L"files/find_in_page/frames.html";
const std::wstring kUserSelectPage = L"files/find_in_page/user-select.html";
const std::wstring kCrashPage = L"files/find_in_page/crash_1341577.html";
const std::wstring kTooFewMatchesPage = L"files/find_in_page/bug_1155639.html";

// This test loads a page with frames and starts FindInPage requests
TEST_F(FindInPageControllerTest, FindInPageFrames) {
  TestServer server(L"chrome/test/data");

  // First we navigate to our frames page.
  GURL url = server.TestServerPageW(kFramePage);
  scoped_ptr<TabProxy> tab(GetActiveTab());
  ASSERT_TRUE(tab->NavigateToURL(url));
  WaitUntilTabCount(1);

  // Try incremental search (mimicking user typing in).
  EXPECT_EQ(18, tab->FindInPage(L"g",       FWD, IGNORE_CASE, false));
  EXPECT_EQ(11, tab->FindInPage(L"go",      FWD, IGNORE_CASE, false));
  EXPECT_EQ(04, tab->FindInPage(L"goo",     FWD, IGNORE_CASE, false));
  EXPECT_EQ(03, tab->FindInPage(L"goog",    FWD, IGNORE_CASE, false));
  EXPECT_EQ(02, tab->FindInPage(L"googl",   FWD, IGNORE_CASE, false));
  EXPECT_EQ(01, tab->FindInPage(L"google",  FWD, IGNORE_CASE, false));
  EXPECT_EQ(00, tab->FindInPage(L"google!", FWD, IGNORE_CASE, false));

  // Negative test (no matches should be found).
  EXPECT_EQ(0, tab->FindInPage(L"Non-existing string", FWD, IGNORE_CASE,
                               false));

  // 'horse' only exists in the three right frames.
  EXPECT_EQ(3, tab->FindInPage(L"horse", FWD, IGNORE_CASE, false));

  // 'cat' only exists in the first frame.
  EXPECT_EQ(1, tab->FindInPage(L"cat", FWD, IGNORE_CASE, false));

  // Try searching again, should still come up with 1 match.
  EXPECT_EQ(1, tab->FindInPage(L"cat", FWD, IGNORE_CASE, false));

  // Try searching backwards, ignoring case, should still come up with 1 match.
  EXPECT_EQ(1, tab->FindInPage(L"CAT", BACK, IGNORE_CASE, false));

  // Try case sensitive, should NOT find it.
  EXPECT_EQ(0, tab->FindInPage(L"CAT", FWD, CASE_SENSITIVE, false));

  // Try again case sensitive, but this time with right case.
  EXPECT_EQ(1, tab->FindInPage(L"dog", FWD, CASE_SENSITIVE, false));

  // Try non-Latin characters ('Hreggvidur' with 'eth' for 'd' in left frame).
  EXPECT_EQ(1, tab->FindInPage(L"Hreggvi\u00F0ur", FWD, IGNORE_CASE, false));
  EXPECT_EQ(1, tab->FindInPage(L"Hreggvi\u00F0ur", FWD, CASE_SENSITIVE, false));
  EXPECT_EQ(0, tab->FindInPage(L"hreggvi\u00F0ur", FWD, CASE_SENSITIVE, false));
}

// Load a page with no selectable text and make sure we don't crash.
TEST_F(FindInPageControllerTest, FindUnSelectableText) {
  TestServer server(L"chrome/test/data");

  GURL url = server.TestServerPageW(kUserSelectPage);
  scoped_ptr<TabProxy> tab(GetActiveTab());
  ASSERT_TRUE(tab->NavigateToURL(url));
  WaitUntilTabCount(1);

  EXPECT_EQ(0, tab->FindInPage(L"text", FWD, IGNORE_CASE, false));
  EXPECT_EQ(0, tab->FindInPage(L"Non-existing string", FWD, IGNORE_CASE,
                               false));
}

// Try to reproduce the crash seen in issue 1341577.
TEST_F(FindInPageControllerTest, FindCrash_Issue1341577) {
  TestServer server(L"chrome/test/data");

  GURL url = server.TestServerPageW(kCrashPage);
  scoped_ptr<TabProxy> tab(GetActiveTab());
  ASSERT_TRUE(tab->NavigateToURL(url));
  WaitUntilTabCount(1);

  // This would crash the tab. These must be the first two find requests issued
  // against the frame, otherwise an active frame pointer is set and it wont
  // produce the crash.
  EXPECT_EQ(1, tab->FindInPage(L"\u0D4C", FWD, IGNORE_CASE, false));
  // FindNext returns -1 for match count because it doesn't bother with
  // recounting the number of matches. We don't care about the match count
  // anyway in this case, we just want to make sure it doesn't crash.
  EXPECT_EQ(-1, tab->FindInPage(L"\u0D4C", FWD, IGNORE_CASE, true));

  // This should work fine.
  EXPECT_EQ(1, tab->FindInPage(L"\u0D24\u0D46", FWD, IGNORE_CASE, false));
  EXPECT_EQ(0, tab->FindInPage(L"nostring", FWD, IGNORE_CASE, false));
}

// Test to make sure Find does the right thing when restarting from a timeout.
// We used to have a problem where we'd stop finding matches when all of the
// following conditions were true:
// 1) The page has a lot of text to search.
// 2) The page contains more than one match.
// 3) It takes longer than the time-slice given to each Find operation (100
//    ms) to find one or more of those matches (so Find times out and has to try
//    again from where it left off).
TEST_F(FindInPageControllerTest, FindEnoughMatches_Issue1155639) {
  TestServer server(L"chrome/test/data");

  GURL url = server.TestServerPageW(kTooFewMatchesPage);
  scoped_ptr<TabProxy> tab(GetActiveTab());
  ASSERT_TRUE(tab->NavigateToURL(url));
  WaitUntilTabCount(1);

  // This string appears 5 times at the bottom of a long page. If Find restarts
  // properly after a timeout, it will find 5 matches, not just 1.
  EXPECT_EQ(5, tab->FindInPage(L"008.xml", FWD, IGNORE_CASE, false));
}

// The find window should not change its location just because we open and close
// a new tab.
TEST_F(FindInPageControllerTest, FindMovesOnTabClose_Issue1343052) {
  fprintf(stderr, "Starting FindMovesOnTabClose_Issue1343052\n");
  TestServer server(L"chrome/test/data");

  fprintf(stderr, "TestServerPageW\n");
  GURL url = server.TestServerPageW(kFramePage);
  fprintf(stderr, "GetActiveTab A\n");
  scoped_ptr<TabProxy> tabA(GetActiveTab());
  fprintf(stderr, "Navigate A\n");
  ASSERT_TRUE(tabA->NavigateToURL(url));
  fprintf(stderr, "WaitUntilTabCount(1) for A\n");
  WaitUntilTabCount(1);

  fprintf(stderr, "GetBrowserWindow(0)\n");
  scoped_ptr<BrowserProxy> browser(automation()->GetBrowserWindow(0));
  ASSERT_TRUE(browser.get() != NULL);

  // Toggle the bookmark bar state.
  fprintf(stderr, "ApplyAccelerator bookmark bar\n");
  browser->ApplyAccelerator(IDC_SHOW_BOOKMARKS_BAR);
  fprintf(stderr, "WaitForBookmarkVisibility\n");
  EXPECT_TRUE(WaitForBookmarkBarVisibilityChange(browser.get(), true));

  // Open the Find window and wait for it to animate.
  fprintf(stderr, "OpenFindInPage in A\n");
  EXPECT_TRUE(tabA->OpenFindInPage());
  fprintf(stderr, "WaitForWindowFullyVisible in A\n");
  EXPECT_TRUE(WaitForFindWindowFullyVisible(tabA.get()));

  // Find its location.
  int x = -1, y = -1;
  fprintf(stderr, "GetFindWindowLocation in A\n");
  EXPECT_TRUE(tabA->GetFindWindowLocation(&x, &y));

  // Open another tab (tab B).
  fprintf(stderr, "AppendTab B\n");
  EXPECT_TRUE(browser->AppendTab(url));
  fprintf(stderr, "GetActiveTab B\n");
  scoped_ptr<TabProxy> tabB(GetActiveTab());

  // Close tab B.
  fprintf(stderr, "Tab Close B\n");
  EXPECT_TRUE(tabB->Close(true));

  // See if the Find window has moved.
  int new_x = -1, new_y = -1;
  fprintf(stderr, "GetFindWindowLocation in A\n");
  EXPECT_TRUE(tabA->GetFindWindowLocation(&new_x, &new_y));

  EXPECT_EQ(x, new_x);
  EXPECT_EQ(y, new_y);

  // Now reset the bookmarks bar state and try the same again.
  fprintf(stderr, "ApplyAccelerator BookmarksBar\n");
  browser->ApplyAccelerator(IDC_SHOW_BOOKMARKS_BAR);
  fprintf(stderr, "WaitForBookmarkBarVisibilityChange\n");
  EXPECT_TRUE(WaitForBookmarkBarVisibilityChange(browser.get(), false));

  // Bookmark bar has moved, reset our coordinates.
  fprintf(stderr, "GetFindWindowLocation again\n");
  EXPECT_TRUE(tabA->GetFindWindowLocation(&x, &y));

  // Open another tab (tab C).
  fprintf(stderr, "Append tab C\n");
  EXPECT_TRUE(browser->AppendTab(url));
  fprintf(stderr, "GetActiveTab C\n");
  scoped_ptr<TabProxy> tabC(GetActiveTab());

  // Close it.
  fprintf(stderr, "Close tab C\n");
  EXPECT_TRUE(tabC->Close(true));

  // See if the Find window has moved.
  fprintf(stderr, "GetFindWindowLocation yet again\n");
  EXPECT_TRUE(tabA->GetFindWindowLocation(&new_x, &new_y));

  EXPECT_EQ(x, new_x);
  EXPECT_EQ(y, new_y);
  fprintf(stderr, "Done!\n");
}
<|endoftext|>


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

#ifndef _OSL_SEMAPHORE_HXX_
#define _OSL_SEMAPHORE_HXX_

#ifdef __cplusplus

#include <osl/semaphor.h>

namespace osl
{

    class Semaphore {
        oslSemaphore semaphore;

    public:

        /** Creates a semaphore.

            @param InitialCount denotes the starting value the semaphore. If you set it to
            zero, the first acquire() blocks. Otherwise InitialCount acquire()s  are
            immedeatly  successfull.
            @return 0 if the semaphore could not be created, otherwise a handle to the sem.
        */

        Semaphore(sal_uInt32 initialCount)
        {
            semaphore = osl_createSemaphore(initialCount);
        }

        /** Release the OS-structures and free semaphore data-structure
            @return fbbb
        */
        ~Semaphore()
        {
            osl_destroySemaphore(semaphore);
        }

        /** acquire() decreases the count. It will block if it tries to
            decrease below zero.
            @return False if the system-call failed.
        */
        sal_Bool acquire()
        {
            return osl_acquireSemaphore(semaphore);
        }

        /** tryToAcquire() tries to decreases the count. It will
            return with False if it would decrease the count below zero.
            (When acquire() would block.) If it could successfully
            decrease the count, it will return True.
        */
        sal_Bool tryToAcquire()
        {
            return osl_tryToAcquireSemaphore(semaphore);
        }

        /** release() increases the count.
            @return False if the system-call failed.
        */
        sal_Bool release()
        {
            return osl_releaseSemaphore(semaphore);
        }
    };
}

#endif  /* __cplusplus */
#endif  /* _OSL_SEMAPHORE_HXX_  */
<commit_msg>INTEGRATION: CWS qdiet01 (1.6.78); FILE MERGED 2003/09/17 09:45:36 obr 1.6.78.1: #110999# made synchrnoization objects non copy constructable / assignable and updated documentation.<commit_after>/*************************************************************************
 *
 *  $RCSfile: semaphor.hxx,v $
 *
 *  $Revision: 1.7 $
 *
 *  last change: $Author: obo $ $Date: 2003-10-20 16:11:08 $
 *
 *  The Contents of this file are made available subject to the terms of
 *  either of the following licenses
 *
 *         - GNU Lesser General Public License Version 2.1
 *         - Sun Industry Standards Source License Version 1.1
 *
 *  Sun Microsystems Inc., October, 2000
 *
 *  GNU Lesser General Public License Version 2.1
 *  =============================================
 *  Copyright 2000 by Sun Microsystems, Inc.
 *  901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License version 2.1, as published by the Free Software Foundation.
 *
 *  This library is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *  Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this library; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *  MA  02111-1307  USA
 *
 *
 *  Sun Industry Standards Source License Version 1.1
 *  =================================================
 *  The contents of this file are subject to the Sun Industry Standards
 *  Source License Version 1.1 (the "License"); You may not use this file
 *  except in compliance with the License. You may obtain a copy of the
 *  License at http://www.openoffice.org/license.html.
 *
 *  Software provided under this License is provided on an "AS IS" basis,
 *  WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
 *  WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
 *  MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
 *  See the License for the specific provisions governing your rights and
 *  obligations concerning the Software.
 *
 *  The Initial Developer of the Original Code is: Sun Microsystems, Inc.
 *
 *  Copyright: 2000 by Sun Microsystems, Inc.
 *
 *  All Rights Reserved.
 *
 *  Contributor(s): _______________________________________
 *
 *
 ************************************************************************/

#ifndef _OSL_SEMAPHORE_HXX_
#define _OSL_SEMAPHORE_HXX_

#ifdef __cplusplus

#include <osl/semaphor.h>

namespace osl
{

    class Semaphore {

    public:

        /** Creates a semaphore.

            @param InitialCount denotes the starting value the semaphore. If you set it to
            zero, the first acquire() blocks. Otherwise InitialCount acquire()s  are
            immedeatly  successfull.
            @return 0 if the semaphore could not be created, otherwise a handle to the sem.
        */

        Semaphore(sal_uInt32 initialCount)
        {
            semaphore = osl_createSemaphore(initialCount);
        }

        /** Release the OS-structures and free semaphore data-structure
            @return fbbb
        */
        ~Semaphore()
        {
            osl_destroySemaphore(semaphore);
        }

        /** acquire() decreases the count. It will block if it tries to
            decrease below zero.
            @return False if the system-call failed.
        */
        sal_Bool acquire()
        {
            return osl_acquireSemaphore(semaphore);
        }

        /** tryToAcquire() tries to decreases the count. It will
            return with False if it would decrease the count below zero.
            (When acquire() would block.) If it could successfully
            decrease the count, it will return True.
        */
        sal_Bool tryToAcquire()
        {
            return osl_tryToAcquireSemaphore(semaphore);
        }

        /** release() increases the count.
            @return False if the system-call failed.
        */
        sal_Bool release()
        {
            return osl_releaseSemaphore(semaphore);
        }

    private:
        oslSemaphore semaphore;

        /** The underlying oslSemaphore has no reference count.

        Since the underlying oslSemaphore is not a reference counted object, copy
        constructed Semaphore may work on an already destructed oslSemaphore object.

        */
        Semaphore(const Semaphore&);

        /** The underlying oslSemaphore has no reference count.

        When destructed, the Semaphore object destroys the undelying oslSemaphore,
        which might cause severe problems in case it's a temporary object.

        */
        Semaphore(oslSemaphore Semaphore);

        /** This assignment operator is private for the same reason as
            the copy constructor.
        */
        Semaphore& operator= (const Semaphore&);

        /** This assignment operator is private for the same reason as
            the constructor taking a oslSemaphore argument.
        */
        Semaphore& operator= (oslSemaphore);
    };
}

#endif  /* __cplusplus */
#endif  /* _OSL_SEMAPHORE_HXX_  */
<|endoftext|>


<commit_before>/*
 Copyright (c) by respective owners including Yahoo!, Microsoft, and
 individual contributors. All rights reserved.  Released under a BSD (revised)
 license as described in the file LICENSE.
 */
#include <fstream>
#include <float.h>
#ifdef _WIN32
#include <winsock2.h>
#else
#include <netdb.h>
#endif
#include <string.h>
#include <stdio.h>
#include <map>
#include "parse_example.h"
#include "constant.h"
#include "sparse_dense.h"
#include "gd.h"
#include "cache.h"
#include "simple_label.h"
#include "rand48.h"
#include "vw.h"
#include <algorithm>
#include "hash.h"
#include <sstream>
#include "parse_primitives.h"

using namespace std;

using namespace LEARNER;

namespace MF {

struct mf {
  vector<string> pairs;

  uint32_t rank;

  uint32_t increment;

  // array to cache w*x, (l^k * x_l) and (r^k * x_r)
  // [ w*(1,x_l,x_r) , l^1*x_l, r^1*x_r, l^2*x_l, r^2*x_2, ... ]
  v_array<float> sub_predictions;

  // array for temp storage of indices
  v_array<unsigned char> indices;

  // array for temp storage of features
  v_array<feature> temp_features;

  vw* all;
};

template <bool cache_sub_predictions>
void predict(mf *data, learner& base, example* ec) {
  vw* all = data->all;

  float prediction = 0;
  if (cache_sub_predictions)
    data->sub_predictions.resize(2*all->rank+1, true);

  // predict from linear terms
  base.predict(ec);

  // store linear prediction
  if (cache_sub_predictions)
    data->sub_predictions[0] = ec->partial_prediction;
  prediction += ec->partial_prediction;

  // store namespace indices
  copy_array(data->indices, ec->indices);

  // add interaction terms to prediction
  for (vector<string>::iterator i = data->pairs.begin(); i != data->pairs.end(); i++) {

    int left_ns = (int) (*i)[0];
    int right_ns = (int) (*i)[1];

    if (ec->atomics[left_ns].size() > 0 && ec->atomics[right_ns].size() > 0) {
      for (size_t k = 1; k <= all->rank; k++) {

	// set example to left namespace only
	ec->indices.erase();
	ec->indices.push_back(left_ns);

	// compute l^k * x_l using base learner
	base.predict(ec, k);
	float x_dot_l = ec->partial_prediction;
	if (cache_sub_predictions)
	  data->sub_predictions[2*k-1] = x_dot_l;

	// set example to right namespace only
	ec->indices.erase();
	ec->indices.push_back(right_ns);

	// compute r^k * x_r using base learner
	base.predict(ec, k + all->rank);
	float x_dot_r = ec->partial_prediction;
	if (cache_sub_predictions)
	  data->sub_predictions[2*k] = x_dot_r;

	// accumulate prediction
	prediction += (x_dot_l * x_dot_r);
      }
    }
  }
  // restore namespace indices and label
  copy_array(ec->indices, data->indices);

  // finalize prediction
  ec->partial_prediction = prediction;
  ec->final_prediction = GD::finalize_prediction(*(data->all), ec->partial_prediction);
}

void learn(mf* data, learner& base, example* ec) {
  vw* all = data->all;

  // predict with current weights
  predict<true>(data, base, ec);

  // update linear weights
  base.update(ec);

  // store namespace indices
  copy_array(data->indices, ec->indices);

  // update interaction terms
  // looping over all pairs of non-empty namespaces
  for (vector<string>::iterator i = data->pairs.begin(); i != data->pairs.end(); i++) {

    int left_ns = (int) (*i)[0];
    int right_ns = (int) (*i)[1];

    if (ec->atomics[left_ns].size() > 0 && ec->atomics[right_ns].size() > 0) {

      // set example to left namespace only
      ec->indices.erase();
      ec->indices.push_back(left_ns);

      // store feature values in left namespace
      copy_array(data->temp_features, ec->atomics[left_ns]);

      for (size_t k = 1; k <= all->rank; k++) {

	// multiply features in left namespace by r^k * x_r
	for (feature* f = ec->atomics[left_ns].begin; f != ec->atomics[left_ns].end; f++)
	  f->x *= data->sub_predictions[2*k];

	// update l^k using base learner
	base.update(ec, k);

	// restore left namespace features (undoing multiply)
	copy_array(ec->atomics[left_ns], data->temp_features);
      }

      // set example to right namespace only
      ec->indices.erase();
      ec->indices.push_back(right_ns);

      // store feature values for right namespace
      copy_array(data->temp_features, ec->atomics[right_ns]);

      for (size_t k = 1; k <= all->rank; k++) {

	// multiply features in right namespace by l^k * x_l
	for (feature* f = ec->atomics[right_ns].begin; f != ec->atomics[right_ns].end; f++)
	  f->x *= data->sub_predictions[2*k-1];

	// update r^k using base learner
	base.update(ec, k + all->rank);

	// restore right namespace features
	copy_array(ec->atomics[right_ns], data->temp_features);
      }
    }
  }
  // restore namespace indices
  copy_array(ec->indices, data->indices);
}

void finish(mf* o) {
  // restore global pairs
  o->all->pairs = o->pairs;

  // clean up local v_arrays
  o->indices.delete_v();
  o->sub_predictions.delete_v();
}

learner* setup(vw& all, po::variables_map& vm) {
  mf* data = new mf;

  // copy global data locally
  data->all = &all;
  data->rank = all.rank;

  // store global pairs in local data structure and clear global pairs
  // for eventual calls to base learner
  data->pairs = all.pairs;
  all.pairs.clear();

  // initialize weights randomly
  if(!vm.count("initial_regressor"))
    {
      for (size_t j = 0; j < (all.reg.weight_mask + 1) / all.reg.stride; j++)
	all.reg.weight_vector[j*all.reg.stride] = (float) (0.1 * frand48());
    }
  learner* l = new learner(data, all.l, 2*data->rank+1);
  l->set_learn<mf, learn>();
  l->set_predict<mf, predict<false> >();
  l->set_finish<mf,finish>();
  return l;
}
}
<commit_msg>faster namespace manipulation<commit_after>/*
 Copyright (c) by respective owners including Yahoo!, Microsoft, and
 individual contributors. All rights reserved.  Released under a BSD (revised)
 license as described in the file LICENSE.
 */
#include <fstream>
#include <float.h>
#ifdef _WIN32
#include <winsock2.h>
#else
#include <netdb.h>
#endif
#include <string.h>
#include <stdio.h>
#include <map>
#include "parse_example.h"
#include "constant.h"
#include "sparse_dense.h"
#include "gd.h"
#include "cache.h"
#include "simple_label.h"
#include "rand48.h"
#include "vw.h"
#include <algorithm>
#include "hash.h"
#include <sstream>
#include "parse_primitives.h"

using namespace std;

using namespace LEARNER;

namespace MF {

struct mf {
  vector<string> pairs;

  uint32_t rank;

  uint32_t increment;

  // array to cache w*x, (l^k * x_l) and (r^k * x_r)
  // [ w*(1,x_l,x_r) , l^1*x_l, r^1*x_r, l^2*x_l, r^2*x_2, ... ]
  v_array<float> sub_predictions;

  // array for temp storage of indices
  v_array<unsigned char> indices;

  // array for temp storage of features
  v_array<feature> temp_features;

  vw* all;
};

template <bool cache_sub_predictions>
void predict(mf *data, learner& base, example* ec) {
  vw* all = data->all;

  float prediction = 0;
  if (cache_sub_predictions)
    data->sub_predictions.resize(2*all->rank+1, true);

  // predict from linear terms
  base.predict(ec);

  // store linear prediction
  if (cache_sub_predictions)
    data->sub_predictions[0] = ec->partial_prediction;
  prediction += ec->partial_prediction;

  // store namespace indices
  copy_array(data->indices, ec->indices);

  // erase indices
  ec->indices.erase();
  ec->indices.push_back(0);

  // add interaction terms to prediction
  for (vector<string>::iterator i = data->pairs.begin(); i != data->pairs.end(); i++) {

    int left_ns = (int) (*i)[0];
    int right_ns = (int) (*i)[1];

    if (ec->atomics[left_ns].size() > 0 && ec->atomics[right_ns].size() > 0) {
      for (size_t k = 1; k <= all->rank; k++) {

	ec->indices[0] = left_ns;

	// compute l^k * x_l using base learner
	base.predict(ec, k);
	float x_dot_l = ec->partial_prediction;
	if (cache_sub_predictions)
	  data->sub_predictions[2*k-1] = x_dot_l;

	// set example to right namespace only
	ec->indices[0] = right_ns;

	// compute r^k * x_r using base learner
	base.predict(ec, k + all->rank);
	float x_dot_r = ec->partial_prediction;
	if (cache_sub_predictions)
	  data->sub_predictions[2*k] = x_dot_r;

	// accumulate prediction
	prediction += (x_dot_l * x_dot_r);
      }
    }
  }
  // restore namespace indices and label
  copy_array(ec->indices, data->indices);

  // finalize prediction
  ec->partial_prediction = prediction;
  ec->final_prediction = GD::finalize_prediction(*(data->all), ec->partial_prediction);
}

void learn(mf* data, learner& base, example* ec) {
  vw* all = data->all;

  // predict with current weights
  predict<true>(data, base, ec);

  // update linear weights
  base.update(ec);

  // store namespace indices
  copy_array(data->indices, ec->indices);

  // erase indices
  ec->indices.erase();
  ec->indices.push_back(0);

  // update interaction terms
  // looping over all pairs of non-empty namespaces
  for (vector<string>::iterator i = data->pairs.begin(); i != data->pairs.end(); i++) {

    int left_ns = (int) (*i)[0];
    int right_ns = (int) (*i)[1];

    if (ec->atomics[left_ns].size() > 0 && ec->atomics[right_ns].size() > 0) {

      // set example to left namespace only
      ec->indices[0] = left_ns;

      // store feature values in left namespace
      copy_array(data->temp_features, ec->atomics[left_ns]);

      for (size_t k = 1; k <= all->rank; k++) {

	// multiply features in left namespace by r^k * x_r
	for (feature* f = ec->atomics[left_ns].begin; f != ec->atomics[left_ns].end; f++)
	  f->x *= data->sub_predictions[2*k];

	// update l^k using base learner
	base.update(ec, k);

	// restore left namespace features (undoing multiply)
	copy_array(ec->atomics[left_ns], data->temp_features);
      }

      // set example to right namespace only
      ec->indices[0] = right_ns;

      // store feature values for right namespace
      copy_array(data->temp_features, ec->atomics[right_ns]);

      for (size_t k = 1; k <= all->rank; k++) {

	// multiply features in right namespace by l^k * x_l
	for (feature* f = ec->atomics[right_ns].begin; f != ec->atomics[right_ns].end; f++)
	  f->x *= data->sub_predictions[2*k-1];

	// update r^k using base learner
	base.update(ec, k + all->rank);

	// restore right namespace features
	copy_array(ec->atomics[right_ns], data->temp_features);
      }
    }
  }
  // restore namespace indices
  copy_array(ec->indices, data->indices);
}

void finish(mf* o) {
  // restore global pairs
  o->all->pairs = o->pairs;

  // clean up local v_arrays
  o->indices.delete_v();
  o->sub_predictions.delete_v();
}

learner* setup(vw& all, po::variables_map& vm) {
  mf* data = new mf;

  // copy global data locally
  data->all = &all;
  data->rank = all.rank;

  // store global pairs in local data structure and clear global pairs
  // for eventual calls to base learner
  data->pairs = all.pairs;
  all.pairs.clear();

  // initialize weights randomly
  if(!vm.count("initial_regressor"))
    {
      for (size_t j = 0; j < (all.reg.weight_mask + 1) / all.reg.stride; j++)
	all.reg.weight_vector[j*all.reg.stride] = (float) (0.1 * frand48());
    }
  learner* l = new learner(data, all.l, 2*data->rank+1);
  l->set_learn<mf, learn>();
  l->set_predict<mf, predict<false> >();
  l->set_finish<mf,finish>();
  return l;
}
}
<|endoftext|>


<commit_before>// Copyright (c) 2006-2008 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 "base/file_util.h"
#include "base/gfx/rect.h"
#include "base/path_service.h"
#include "base/perftimer.h"
#include "base/time.h"
#include "chrome/app/chrome_dll_resource.h"
#include "chrome/common/chrome_paths.h"
#include "chrome/common/chrome_switches.h"
#include "chrome/test/automation/browser_proxy.h"
#include "chrome/test/automation/window_proxy.h"
#include "chrome/test/ui/ui_test.h"
#include "net/base/net_util.h"

using base::TimeDelta;

namespace {

class NewTabUIStartupTest : public UITest {
 public:
  NewTabUIStartupTest() {
    show_window_ = true;
  }

  void SetUp() {}
  void TearDown() {}

  static const int kNumCycles = 5;

  void PrintTimings(const char* label, TimeDelta timings[kNumCycles],
                    bool important) {
    std::string times;
    for (int i = 0; i < kNumCycles; ++i)
      StringAppendF(&times, "%.2f,", timings[i].InMillisecondsF());
    PrintResultList("new_tab", "", label, times, "ms", important);
  }

  // Run the test, by bringing up a browser and timing the new tab startup.
  // |want_warm| is true if we should output warm-disk timings, false if
  // we should report cold timings.
  void RunStartupTest(const char* label, bool want_warm, bool important,
                      int profile_type) {
    // Install the location of the test profile file.
    set_template_user_data(UITest::ComputeTypicalUserDataSource(
        profile_type).ToWStringHack());

    // Disable the first run notification because it has an animation which
    // masks any real performance regressions.
    launch_arguments_.AppendSwitch(switches::kDisableNewTabFirstRun);

    TimeDelta timings[kNumCycles];
    for (int i = 0; i < kNumCycles; ++i) {
      UITest::SetUp();

      // Switch to the "new tab" tab, which should be any new tab after the
      // first (the first is about:blank).
      scoped_refptr<BrowserProxy> window(automation()->GetBrowserWindow(0));
      ASSERT_TRUE(window.get());

      // We resize the window so that we hit the normal layout of the NTP and
      // not the small layout mode.
#if defined(OS_WIN)
// TODO(port): SetBounds returns false when not implemented.
// It is OK to comment out the resize since it will still be useful to test the
// default size of the window.
      ASSERT_TRUE(window->GetWindow().get()->SetBounds(gfx::Rect(1000, 1000)));
#endif
      int tab_count = -1;
      ASSERT_TRUE(window->GetTabCount(&tab_count));
      ASSERT_EQ(1, tab_count);

      // Hit ctl-t and wait for the tab to load.
      window->ApplyAccelerator(IDC_NEW_TAB);
      ASSERT_TRUE(window->WaitForTabCountToBecome(2, 5000));
      int load_time;
      ASSERT_TRUE(automation()->WaitForInitialNewTabUILoad(&load_time));
      timings[i] = TimeDelta::FromMilliseconds(load_time);

      if (want_warm) {
        // Bring up a second tab, now that we've already shown one tab.
        window->ApplyAccelerator(IDC_NEW_TAB);
        ASSERT_TRUE(window->WaitForTabCountToBecome(3, 5000));
        ASSERT_TRUE(automation()->WaitForInitialNewTabUILoad(&load_time));
        timings[i] = TimeDelta::FromMilliseconds(load_time);
      }

      window = NULL;
      UITest::TearDown();
    }

    PrintTimings(label, timings, important);
  }
};

// TODO(pamg): run these tests with a reference build?
TEST_F(NewTabUIStartupTest, PerfCold) {
  RunStartupTest("tab_cold", false /* cold */, true /* important */,
                 UITest::DEFAULT_THEME);
}

TEST_F(NewTabUIStartupTest, DISABLED_PerfWarm) {
  RunStartupTest("tab_warm", true /* warm */, false /* not important */,
                 UITest::DEFAULT_THEME);
}

TEST_F(NewTabUIStartupTest, ComplexThemeCold) {
  RunStartupTest("tab_complex_theme_cold", false /* cold */,
                 false /* not important */,
                 UITest::COMPLEX_THEME);
}

}  // namespace
<commit_msg>Turn off startup test until I figure out problem.<commit_after>// Copyright (c) 2006-2008 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 "base/file_util.h"
#include "base/gfx/rect.h"
#include "base/path_service.h"
#include "base/perftimer.h"
#include "base/time.h"
#include "chrome/app/chrome_dll_resource.h"
#include "chrome/common/chrome_paths.h"
#include "chrome/common/chrome_switches.h"
#include "chrome/test/automation/browser_proxy.h"
#include "chrome/test/automation/window_proxy.h"
#include "chrome/test/ui/ui_test.h"
#include "net/base/net_util.h"

using base::TimeDelta;

namespace {

class NewTabUIStartupTest : public UITest {
 public:
  NewTabUIStartupTest() {
    show_window_ = true;
  }

  void SetUp() {}
  void TearDown() {}

  static const int kNumCycles = 5;

  void PrintTimings(const char* label, TimeDelta timings[kNumCycles],
                    bool important) {
    std::string times;
    for (int i = 0; i < kNumCycles; ++i)
      StringAppendF(&times, "%.2f,", timings[i].InMillisecondsF());
    PrintResultList("new_tab", "", label, times, "ms", important);
  }

  // Run the test, by bringing up a browser and timing the new tab startup.
  // |want_warm| is true if we should output warm-disk timings, false if
  // we should report cold timings.
  void RunStartupTest(const char* label, bool want_warm, bool important,
                      int profile_type) {
    // Install the location of the test profile file.
    set_template_user_data(UITest::ComputeTypicalUserDataSource(
        profile_type).ToWStringHack());

    // Disable the first run notification because it has an animation which
    // masks any real performance regressions.
    launch_arguments_.AppendSwitch(switches::kDisableNewTabFirstRun);

    TimeDelta timings[kNumCycles];
    for (int i = 0; i < kNumCycles; ++i) {
      UITest::SetUp();

      // Switch to the "new tab" tab, which should be any new tab after the
      // first (the first is about:blank).
      scoped_refptr<BrowserProxy> window(automation()->GetBrowserWindow(0));
      ASSERT_TRUE(window.get());

      // We resize the window so that we hit the normal layout of the NTP and
      // not the small layout mode.
#if defined(OS_WIN)
// TODO(port): SetBounds returns false when not implemented.
// It is OK to comment out the resize since it will still be useful to test the
// default size of the window.
      ASSERT_TRUE(window->GetWindow().get()->SetBounds(gfx::Rect(1000, 1000)));
#endif
      int tab_count = -1;
      ASSERT_TRUE(window->GetTabCount(&tab_count));
      ASSERT_EQ(1, tab_count);

      // Hit ctl-t and wait for the tab to load.
      window->ApplyAccelerator(IDC_NEW_TAB);
      ASSERT_TRUE(window->WaitForTabCountToBecome(2, 5000));
      int load_time;
      ASSERT_TRUE(automation()->WaitForInitialNewTabUILoad(&load_time));
      timings[i] = TimeDelta::FromMilliseconds(load_time);

      if (want_warm) {
        // Bring up a second tab, now that we've already shown one tab.
        window->ApplyAccelerator(IDC_NEW_TAB);
        ASSERT_TRUE(window->WaitForTabCountToBecome(3, 5000));
        ASSERT_TRUE(automation()->WaitForInitialNewTabUILoad(&load_time));
        timings[i] = TimeDelta::FromMilliseconds(load_time);
      }

      window = NULL;
      UITest::TearDown();
    }

    PrintTimings(label, timings, important);
  }
};

// TODO(pamg): run these tests with a reference build?
TEST_F(NewTabUIStartupTest, PerfCold) {
  RunStartupTest("tab_cold", false /* cold */, true /* important */,
                 UITest::DEFAULT_THEME);
}

TEST_F(NewTabUIStartupTest, DISABLED_PerfWarm) {
  RunStartupTest("tab_warm", true /* warm */, false /* not important */,
                 UITest::DEFAULT_THEME);
}

//TEST_F(NewTabUIStartupTest, ComplexThemeCold) {
//  RunStartupTest("tab_complex_theme_cold", false /* cold */,
//                 false /* not important */,
//                 UITest::COMPLEX_THEME);
//}

}  // namespace
<|endoftext|>


<commit_before>// RUN: cat %s | %cling -Xclang -verify -I%p | FileCheck %s
// XFAIL: *

// Test the ability of including a wrong file see diagnostics and remove the
// cached files so that all the changes are going to be seen next time it gets
// included.

#include <iostream>
#include <fstream>
std::ofstream myfile;
myfile.open("TmpClassDef.h");
myfile << "class MyClass{};\n"
myfile << "error_here;";
myfile << "// expected-error {{C++ requires a type specifier for all declarations}}\n"
myfile.close();
#include "TmpClassDef.h"

myfile.open("TmpClassDef.h");
myfile << "class MyClass{ \n";
myfile << "public: \n";
myfile << "  int gimme12(){\n";
myfile << "    return 12;\n"
myfile << "  }\n"
myfile << "};\n";
myfile.close();
#include "TmpClassDef.h"

MyClass my;
my.gimme12()
// CHECK: (int const) 12
<commit_msg>With our resent patches in clang's cache system we are able to invalidate a cached file. This means that we can mark the test as expected to succeed.<commit_after>// RUN: cat %s | %cling -Xclang -verify -I%p | FileCheck %s

// Test the ability of including a wrong file see diagnostics and remove the
// cached files so that all the changes are going to be seen next time it gets
// included.

#include <iostream>
#include <fstream>
std::ofstream myfile;
myfile.open("TmpClassDef.h");
myfile << "class MyClass{};\n"
myfile << "error_here;";
myfile << "// expected-error {{C++ requires a type specifier for all declarations}}\n"
myfile.close();
#include "TmpClassDef.h"

myfile.open("TmpClassDef.h");
myfile << "class MyClass{ \n";
myfile << "public: \n";
myfile << "  int gimme12(){\n";
myfile << "    return 12;\n"
myfile << "  }\n"
myfile << "};\n";
myfile.close();
#include "TmpClassDef.h"

MyClass my;
my.gimme12()
// CHECK: (int const) 12
<|endoftext|>


<commit_before>#include "density.h"

namespace sirius {

Density::Density(Simulation_context& ctx__)
    : ctx_(ctx__),
      unit_cell_(ctx_.unit_cell()),
      rho_pseudo_core_(nullptr),
      gaunt_coefs_(nullptr),
      high_freq_mixer_(nullptr),
      low_freq_mixer_(nullptr),
      mixer_(nullptr)
{
    rho_ = new Periodic_function<double>(ctx_, ctx_.lmmax_rho(), 1);

    /* core density of the pseudopotential method */
    if (!ctx_.full_potential())
    {
        rho_pseudo_core_ = new Periodic_function<double>(ctx_, 0, false);
        rho_pseudo_core_->zero();

        generate_pseudo_core_charge_density();
    }

    for (int i = 0; i < ctx_.num_mag_dims(); i++)
        magnetization_[i] = new Periodic_function<double>(ctx_, ctx_.lmmax_rho(), 1);

    switch (ctx_.esm_type())
    {
        case full_potential_lapwlo:
        {
            gaunt_coefs_ = new Gaunt_coefficients<double_complex>(ctx_.lmax_apw(), ctx_.lmax_rho(),
                                                                  ctx_.lmax_apw(), SHT::gaunt_hybrid);
            break;
        }
        case full_potential_pwlo:
        {
            gaunt_coefs_ = new Gaunt_coefficients<double_complex>(ctx_.lmax_pw(), ctx_.lmax_rho(),
                                                                  ctx_.lmax_pw(), SHT::gaunt_hybrid);
            break;
        }

        case paw_pseudopotential:
        case ultrasoft_pseudopotential:
        case norm_conserving_pseudopotential:
        {
            break;
        }
    }

    l_by_lm_ = Utils::l_by_lm(ctx_.lmax_rho());

    if (!ctx_.full_potential())
    {
        lf_gvec_ = std::vector<int>(ctx_.gvec_coarse().num_gvec());
        std::vector<double> weights(ctx_.gvec_coarse().num_gvec() * (1 + ctx_.num_mag_dims()), 1.0);

        weights[0] = 0;
        lf_gvec_[0] = 0;

        for (int ig = 1; ig < ctx_.gvec_coarse().num_gvec(); ig++)
        {
            auto G = ctx_.gvec_coarse()[ig];
            /* save index of low-frequency G-vector */
            lf_gvec_[ig] = ctx_.gvec().index_by_gvec(G);
            weights[ig] = fourpi * unit_cell_.omega() / std::pow(ctx_.gvec_coarse().gvec_len(ig), 2);
        }

        /* find high-frequency G-vectors */
        for (int ig = 0; ig < ctx_.gvec().num_gvec(); ig++)
        {
            if (ctx_.gvec().gvec_len(ig) > 2 * ctx_.gk_cutoff()) hf_gvec_.push_back(ig);
        }

        if (static_cast<int>(hf_gvec_.size()) != ctx_.gvec().num_gvec() - ctx_.gvec_coarse().num_gvec())
        {
            std::stringstream s;
            s << "Wrong count of high-frequency G-vectors" << std::endl
              << "number of found high-frequency G-vectors: " << hf_gvec_.size() << std::endl
              << "expected number of high-frequency G-vectors: " << ctx_.gvec().num_gvec() - ctx_.gvec_coarse().num_gvec() << std::endl
              << "G-vector cutoff: " <<  ctx_.gk_cutoff();
            TERMINATE(s);
        }

        high_freq_mixer_ = new Linear_mixer<double_complex>(hf_gvec_.size() * (1 + ctx_.num_mag_dims()),
                                                            ctx_.mixer_input_section().beta_, ctx_.comm());

        if (ctx_.mixer_input_section().type_ == "linear")
        {
            low_freq_mixer_ = new Linear_mixer<double_complex>(lf_gvec_.size() * (1 + ctx_.num_mag_dims()),
                                                               ctx_.mixer_input_section().beta_, ctx_.comm());
        }
        else if (ctx_.mixer_input_section().type_ == "broyden1")
        {

            low_freq_mixer_ = new Broyden1<double_complex>(lf_gvec_.size() * (1 + ctx_.num_mag_dims()),
                                                           ctx_.mixer_input_section().max_history_,
                                                           ctx_.mixer_input_section().beta_,
                                                           weights,
                                                           ctx_.comm());
        }
        else if (ctx_.mixer_input_section().type_ == "broyden2")
        {
            low_freq_mixer_ = new Broyden2<double_complex>(lf_gvec_.size() * (1 + ctx_.num_mag_dims()),
                                                           ctx_.mixer_input_section().max_history_,
                                                           ctx_.mixer_input_section().beta_,
                                                           ctx_.mixer_input_section().beta0_,
                                                           ctx_.mixer_input_section().linear_mix_rms_tol_,
                                                           weights,
                                                           ctx_.comm());
        }
        else
        {
            TERMINATE("wrong mixer type");
        }
    }

    if (ctx_.full_potential())
    {
        if (ctx_.mixer_input_section().type_ == "linear")
        {
            mixer_ = new Linear_mixer<double>(size(),
                                              ctx_.mixer_input_section().beta_,
                                              ctx_.comm());
        }
        else if (ctx_.mixer_input_section().type_ == "broyden1")
        {
            std::vector<double> weights;
            mixer_ = new Broyden1<double>(size(),
                                          ctx_.mixer_input_section().max_history_,
                                          ctx_.mixer_input_section().beta_,
                                          weights,
                                          ctx_.comm());
        }
        else if (ctx_.mixer_input_section().type_ == "broyden2")
        {
            std::vector<double> weights;
            mixer_ = new Broyden2<double>(size(),
                                          ctx_.mixer_input_section().max_history_,
                                          ctx_.mixer_input_section().beta_,
                                          ctx_.mixer_input_section().beta0_,
                                          ctx_.mixer_input_section().linear_mix_rms_tol_,
                                          weights,
                                          ctx_.comm());

        }
        else
        {
            TERMINATE("wrong mixer type");
        }
    }

    /* If we have ud and du spin blocks, don't compute one of them (du in this implementation)
     * because density matrix is symmetric. */
    int ndm = std::max(ctx_.num_mag_dims(), ctx_.num_spins());

    if (ctx_.full_potential()) {
        density_matrix_ = mdarray<double_complex, 4>(unit_cell_.max_mt_basis_size(), unit_cell_.max_mt_basis_size(),
                                                     ndm, unit_cell_.spl_num_atoms().local_size());
    } else {
        density_matrix_ = mdarray<double_complex, 4>(unit_cell_.max_mt_basis_size(), unit_cell_.max_mt_basis_size(),
                                                     ndm, unit_cell_.num_atoms());
    }

    //--- Allocate local PAW density arrays ---

    for(int ia = 0; ia < unit_cell_.num_atoms(); ia++)
    {
        auto& atom = unit_cell_.atom(ia);

        auto& atype = atom.type();

        int n_mt_points = atype.num_mt_points();

        int rad_func_lmax = atype.indexr().lmax_lo();

        int n_rho_lm_comp = Utils::lmmax(rad_func_lmax);

        // allocate
        mdarray<double, 2> ae_atom_density(n_rho_lm_comp, n_mt_points);
        mdarray<double, 2> ps_atom_density(n_rho_lm_comp, n_mt_points);

        // add
        paw_ae_local_density_.push_back(std::move(ae_atom_density));
        paw_ps_local_density_.push_back(std::move(ps_atom_density));

        // magnetization
        mdarray<double, 3> ae_atom_magn(n_rho_lm_comp, n_mt_points, 3);
        mdarray<double, 3> ps_atom_magn(n_rho_lm_comp, n_mt_points, 3);

        ae_atom_magn.zero();
        ps_atom_magn.zero();

        paw_ae_local_magnetization_.push_back(std::move(ae_atom_magn));
        paw_ps_local_magnetization_.push_back(std::move(ps_atom_magn));

    }

}

Density::~Density()
{
    delete rho_;
    for (int j = 0; j < ctx_.num_mag_dims(); j++) delete magnetization_[j];

    if (rho_pseudo_core_ != nullptr) delete rho_pseudo_core_;
    if (gaunt_coefs_ != nullptr) delete gaunt_coefs_;
    if (low_freq_mixer_ != nullptr) delete low_freq_mixer_;
    if (high_freq_mixer_ != nullptr) delete high_freq_mixer_;
    if (mixer_ != nullptr) delete mixer_;
}

};
<commit_msg>minor fix<commit_after>#include "density.h"

namespace sirius {

Density::Density(Simulation_context& ctx__)
    : ctx_(ctx__),
      unit_cell_(ctx_.unit_cell()),
      rho_pseudo_core_(nullptr),
      gaunt_coefs_(nullptr),
      high_freq_mixer_(nullptr),
      low_freq_mixer_(nullptr),
      mixer_(nullptr)
{
    rho_ = new Periodic_function<double>(ctx_, ctx_.lmmax_rho(), 1);

    /* core density of the pseudopotential method */
    if (!ctx_.full_potential())
    {
        rho_pseudo_core_ = new Periodic_function<double>(ctx_, 0, false);
        rho_pseudo_core_->zero();

        generate_pseudo_core_charge_density();
    }

    for (int i = 0; i < ctx_.num_mag_dims(); i++)
        magnetization_[i] = new Periodic_function<double>(ctx_, ctx_.lmmax_rho(), 1);

    switch (ctx_.esm_type())
    {
        case full_potential_lapwlo:
        {
            gaunt_coefs_ = new Gaunt_coefficients<double_complex>(ctx_.lmax_apw(), ctx_.lmax_rho(),
                                                                  ctx_.lmax_apw(), SHT::gaunt_hybrid);
            break;
        }
        case full_potential_pwlo:
        {
            gaunt_coefs_ = new Gaunt_coefficients<double_complex>(ctx_.lmax_pw(), ctx_.lmax_rho(),
                                                                  ctx_.lmax_pw(), SHT::gaunt_hybrid);
            break;
        }

        case paw_pseudopotential:
        case ultrasoft_pseudopotential:
        case norm_conserving_pseudopotential:
        {
            break;
        }
    }

    l_by_lm_ = Utils::l_by_lm(ctx_.lmax_rho());

    if (!ctx_.full_potential())
    {
        lf_gvec_ = std::vector<int>(ctx_.gvec_coarse().num_gvec());
        std::vector<double> weights(ctx_.gvec_coarse().num_gvec() * (1 + ctx_.num_mag_dims()), 1.0);

        weights[0] = 0;
        lf_gvec_[0] = 0;

        for (int ig = 1; ig < ctx_.gvec_coarse().num_gvec(); ig++)
        {
            auto G = ctx_.gvec_coarse()[ig];
            /* save index of low-frequency G-vector */
            lf_gvec_[ig] = ctx_.gvec().index_by_gvec(G);
            weights[ig] = fourpi * unit_cell_.omega() / std::pow(ctx_.gvec_coarse().gvec_len(ig), 2);
        }

        /* find high-frequency G-vectors */
        for (int ig = 0; ig < ctx_.gvec().num_gvec(); ig++)
        {
            if (ctx_.gvec().gvec_len(ig) > 2 * ctx_.gk_cutoff()) hf_gvec_.push_back(ig);
        }

        if (static_cast<int>(hf_gvec_.size()) != ctx_.gvec().num_gvec() - ctx_.gvec_coarse().num_gvec())
        {
            std::stringstream s;
            s << "Wrong count of high-frequency G-vectors" << std::endl
              << "number of found high-frequency G-vectors: " << hf_gvec_.size() << std::endl
              << "expected number of high-frequency G-vectors: " << ctx_.gvec().num_gvec() - ctx_.gvec_coarse().num_gvec() << std::endl
              << "G-vector cutoff: " <<  ctx_.gk_cutoff();
            TERMINATE(s);
        }

        high_freq_mixer_ = new Linear_mixer<double_complex>(hf_gvec_.size() * (1 + ctx_.num_mag_dims()),
                                                            ctx_.mixer_input_section().beta_, ctx_.comm());

        if (ctx_.mixer_input_section().type_ == "linear")
        {
            low_freq_mixer_ = new Linear_mixer<double_complex>(lf_gvec_.size() * (1 + ctx_.num_mag_dims()),
                                                               ctx_.mixer_input_section().beta_, ctx_.comm());
        }
        else if (ctx_.mixer_input_section().type_ == "broyden1")
        {

            low_freq_mixer_ = new Broyden1<double_complex>(lf_gvec_.size() * (1 + ctx_.num_mag_dims()),
                                                           ctx_.mixer_input_section().max_history_,
                                                           ctx_.mixer_input_section().beta_,
                                                           weights,
                                                           ctx_.comm());
        }
        else if (ctx_.mixer_input_section().type_ == "broyden2")
        {
            low_freq_mixer_ = new Broyden2<double_complex>(lf_gvec_.size() * (1 + ctx_.num_mag_dims()),
                                                           ctx_.mixer_input_section().max_history_,
                                                           ctx_.mixer_input_section().beta_,
                                                           ctx_.mixer_input_section().beta0_,
                                                           ctx_.mixer_input_section().linear_mix_rms_tol_,
                                                           weights,
                                                           ctx_.comm());
        }
        else
        {
            TERMINATE("wrong mixer type");
        }
    }

    if (ctx_.full_potential())
    {
        if (ctx_.mixer_input_section().type_ == "linear")
        {
            mixer_ = new Linear_mixer<double>(size(),
                                              ctx_.mixer_input_section().beta_,
                                              ctx_.comm());
        }
        else if (ctx_.mixer_input_section().type_ == "broyden1")
        {
            std::vector<double> weights;
            mixer_ = new Broyden1<double>(size(),
                                          ctx_.mixer_input_section().max_history_,
                                          ctx_.mixer_input_section().beta_,
                                          weights,
                                          ctx_.comm());
        }
        else if (ctx_.mixer_input_section().type_ == "broyden2")
        {
            std::vector<double> weights;
            mixer_ = new Broyden2<double>(size(),
                                          ctx_.mixer_input_section().max_history_,
                                          ctx_.mixer_input_section().beta_,
                                          ctx_.mixer_input_section().beta0_,
                                          ctx_.mixer_input_section().linear_mix_rms_tol_,
                                          weights,
                                          ctx_.comm());

        }
        else
        {
            TERMINATE("wrong mixer type");
        }
    }

    /* If we have ud and du spin blocks, don't compute one of them (du in this implementation)
     * because density matrix is symmetric. */
    int ndm = std::max(ctx_.num_mag_dims(), ctx_.num_spins());

    if (ctx_.full_potential()) {
        density_matrix_ = mdarray<double_complex, 4>(unit_cell_.max_mt_basis_size(), unit_cell_.max_mt_basis_size(),
                                                     ndm, unit_cell_.spl_num_atoms().local_size());
    } else {
        density_matrix_ = mdarray<double_complex, 4>(unit_cell_.max_mt_basis_size(), unit_cell_.max_mt_basis_size(),
                                                     ndm, unit_cell_.num_atoms());
    }

    //--- Allocate local PAW density arrays ---

    for(int ia = 0; ia < unit_cell_.num_atoms(); ia++)
    {
        auto& atom = unit_cell_.atom(ia);

        auto& atype = atom.type();

        int n_mt_points = atype.num_mt_points();

        // allocate
        mdarray<double, 2> ae_atom_density(ctx_.lmmax_rho(), n_mt_points);
        mdarray<double, 2> ps_atom_density(ctx_.lmmax_rho(), n_mt_points);

        // add
        paw_ae_local_density_.push_back(std::move(ae_atom_density));
        paw_ps_local_density_.push_back(std::move(ps_atom_density));

        // magnetization
        mdarray<double, 3> ae_atom_magn(ctx_.lmmax_rho(), n_mt_points, 3);
        mdarray<double, 3> ps_atom_magn(ctx_.lmmax_rho(), n_mt_points, 3);

        ae_atom_magn.zero();
        ps_atom_magn.zero();

        paw_ae_local_magnetization_.push_back(std::move(ae_atom_magn));
        paw_ps_local_magnetization_.push_back(std::move(ps_atom_magn));

    }

}

Density::~Density()
{
    delete rho_;
    for (int j = 0; j < ctx_.num_mag_dims(); j++) delete magnetization_[j];

    if (rho_pseudo_core_ != nullptr) delete rho_pseudo_core_;
    if (gaunt_coefs_ != nullptr) delete gaunt_coefs_;
    if (low_freq_mixer_ != nullptr) delete low_freq_mixer_;
    if (high_freq_mixer_ != nullptr) delete high_freq_mixer_;
    if (mixer_ != nullptr) delete mixer_;
}

};
<|endoftext|>


<commit_before>// See LICENSE file for copyright and license details.

#include <cassert>
#include <SDL/SDL.h>
#include <SDL/SDL_opengl.h>
#include <SDL/SDL_image.h>
#include "core/misc.hpp"
#include "ui/gl.hpp"

static GLenum getTextureFormat(
    const SDL_Surface* surface, int nOfColors)
{
  if (nOfColors == 4) {
    // contains an alpha channel
    if (surface->format->Rmask == 0xff) {
      return GL_RGBA;
    } else {
      return GL_BGRA;
    }
  } else if (nOfColors == 3) {
    // no alpha channel
    if (surface->format->Rmask == 0xff) {
      return GL_RGB;
    } else {
      return GL_BGR;
    }
  } else {
    die("gl.c: loadTexture(): "
        "the image is not truecolor.."
        "  this will probably break\n");
    return 0;
  }
}

static void setTextureParameters() {
  glTexParameteri(GL_TEXTURE_2D,
      GL_TEXTURE_WRAP_S, GL_REPEAT);
  glTexParameteri(GL_TEXTURE_2D,
      GL_TEXTURE_WRAP_T, GL_REPEAT);
  glTexParameteri(GL_TEXTURE_2D,
      GL_TEXTURE_MAG_FILTER, GL_LINEAR);
  glTexParameteri(GL_TEXTURE_2D,
      GL_TEXTURE_MIN_FILTER,
      GL_LINEAR_MIPMAP_LINEAR);
  glTexParameteri(GL_TEXTURE_2D,
      GL_GENERATE_MIPMAP, GL_TRUE);
}

static bool isPowerOfTwo(int n) {
  return ((n & (n - 1)) == 0);
}

int loadTexture(const char *filename) {
  GLuint id;
  SDL_Surface* surface = IMG_Load(filename);
  if (!surface) {
    die("gl.c: loadTexture(): Can't load file '%s'\n",
        filename);
    return 0;
  }
  if (!isPowerOfTwo(surface->w)
      || !isPowerOfTwo(surface->h))
  {
    die("ui/gl.c: loadTexture(): "
        "image's height or width is not a power of 2\n");
  }
  GLint nOfColors = surface->format->BytesPerPixel;
  GLenum textureFormat = getTextureFormat(surface, nOfColors);
  glGenTextures(1, &id);
  glBindTexture(GL_TEXTURE_2D, id);
  setTextureParameters();
  glTexImage2D(GL_TEXTURE_2D, 0, nOfColors,
      surface->w, surface->h, 0,
      textureFormat, GL_UNSIGNED_BYTE, surface->pixels);
  if (surface) {
    SDL_FreeSurface(surface);
  }
  return static_cast<int>(id);
}
<commit_msg>Small fixes in ui/gl.cpp<commit_after>// See LICENSE file for copyright and license details.

#include <cassert>
#include <SDL/SDL.h>
#include <SDL/SDL_opengl.h>
#include <SDL/SDL_image.h>
#include "core/misc.hpp"
#include "ui/gl.hpp"

static GLenum getTextureFormat(
    const SDL_Surface* surface, int nOfColors)
{
  if (nOfColors == 4) {
    // contains an alpha channel
    if (surface->format->Rmask == 0xff) {
      return GL_RGBA;
    } else {
      return GL_BGRA;
    }
  } else if (nOfColors == 3) {
    // no alpha channel
    if (surface->format->Rmask == 0xff) {
      return GL_RGB;
    } else {
      return GL_BGR;
    }
  } else {
    die("gl.c: loadTexture(): "
        "the image is not truecolor.."
        "  this will probably break\n");
    return 0;
  }
}

static void setTextureParameters() {
  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
  glTexParameteri(GL_TEXTURE_2D,
      GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
  glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP, GL_TRUE);
}

static bool isPowerOfTwo(int n) {
  return ((n & (n - 1)) == 0);
}

int loadTexture(const char *filename) {
  SDL_Surface* surface = IMG_Load(filename);
  if (!surface) {
    die("gl.c: loadTexture(): Can't load file '%s'\n",
        filename);
  }
  if (!isPowerOfTwo(surface->w) || !isPowerOfTwo(surface->h)) {
    die("ui/gl.c: loadTexture(): "
        "image's height or width is not a power of 2\n");
  }
  GLint nOfColors = surface->format->BytesPerPixel;
  GLenum textureFormat = getTextureFormat(surface, nOfColors);
  GLuint id;
  glGenTextures(1, &id);
  glBindTexture(GL_TEXTURE_2D, id);
  setTextureParameters();
  glTexImage2D(GL_TEXTURE_2D, 0, nOfColors,
      surface->w, surface->h, 0,
      textureFormat, GL_UNSIGNED_BYTE, surface->pixels);
  SDL_FreeSurface(surface);
  return static_cast<int>(id);
}
<|endoftext|>


<commit_before>/*****************************************************************************\
 *                        ANALYSIS PERFORMANCE TOOLS                         *
 *                               libparaver-api                              *
 *                      API Library for libparaver-kernel                    *
 *****************************************************************************
 *     ___     This library is free software; you can redistribute it and/or *
 *    /  __         modify it under the terms of the GNU LGPL as published   *
 *   /  /  _____    by the Free Software Foundation; either version 2.1      *
 *  /  /  /     \   of the License, or (at your option) any later version.   *
 * (  (  ( B S C )                                                           *
 *  \  \  \_____/   This library is distributed in hope that it will be      *
 *   \  \__         useful but WITHOUT ANY WARRANTY; without even the        *
 *    \___          implied warranty of MERCHANTABILITY or FITNESS FOR A     *
 *                  PARTICULAR PURPOSE. See the GNU LGPL for more details.   *
 *                                                                           *
 * You should have received a copy of the GNU Lesser General Public License  *
 * along with this library; if not, write to the Free Software Foundation,   *
 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA          *
 * The GNU LEsser General Public License is contained in the file COPYING.   *
 *                                 ---------                                 *
 *   Barcelona Supercomputing Center - Centro Nacional de Supercomputacion   *
\*****************************************************************************/

/* -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- *\
 | @file: $HeadURL$
 | @last_commit: $Date$
 | @version:     $Revision$
\* -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */

#include "tracecutter.h"
//#include "ktraceoptions.h"
#include "traceoptions.h"
//#include "ktracecutter.h"
#include "kernelconnection.h"
#include "pcfparser/ParaverTraceConfig.h"
using namespace libparaver;
#include <map>
#include <string.h>
#include "eventlabels.h"

using namespace std;

string TraceCutter::traceToolID = "cutter";
string TraceCutter::traceToolName = "Cutter";
string TraceCutter::traceToolExtension = "chop";

TraceCutter *TraceCutter::create(  KernelConnection *whichKernel,
                                   char *traceIn,
                                   char *traceOut,
                                   TraceOptions *options,
                                   ProgressController *progress )
{
  return new TraceCutterProxy( whichKernel, traceIn, traceOut, options, progress );
}

TraceCutterProxy::TraceCutterProxy( const KernelConnection *whichKernel,
                                    char *traceIn,
                                    char *traceOut,
                                    TraceOptions *options,
                                    ProgressController *progress )
{
//  char *pcf_name, *c;
  std::string pcf_name;
  FILE *pcfFile;
  vector< TEventType > typesWithValueZero;

/*  pcf_name = strdup( traceIn );
  c = strrchr( pcf_name, '.' );
  sprintf( c, ".pcf" );*/

  pcf_name = LocalKernel::composeName( traceIn, string( "pcf" ) );
  if(( pcfFile = fopen( pcf_name.c_str(), "r" )) != NULL )
  {
    fclose( pcfFile );

    ParaverTraceConfig *config = new ParaverTraceConfig( pcf_name );
    EventLabels myEventLabels = EventLabels( *config, set<TEventType>() );
    vector< TEventType > allTypes;
    EventLabels labels;
    labels.getTypes( allTypes );
    map< TEventValue, string > currentEventValues;
    for( vector< TEventType >::iterator it = allTypes.begin(); it != allTypes.end(); ++it )
    {
      if ( labels.getValues( *it, currentEventValues ) )
      {
        if ( currentEventValues.find( TEventValue( 0 )) != currentEventValues.end() )
        {
          typesWithValueZero.push_back( *it );
        }
        currentEventValues.clear();
      }
    }

    delete config;
  }

  myTraceCutter = whichKernel->newTraceCutter( options, typesWithValueZero );
  myTraceCutter->execute( traceIn, traceOut, progress );
}

TraceCutterProxy::~TraceCutterProxy()
{
  delete myTraceCutter;
}

void TraceCutterProxy::execute( char *trace_in, char *trace_out, ProgressController *progress )
{
  myTraceCutter->execute( trace_in, trace_out, progress );
}

void TraceCutterProxy::set_by_time( bool whichByTime )
{
  myTraceCutter->set_by_time( whichByTime );
}

void TraceCutterProxy::set_min_cutting_time( unsigned long long minCutTime )
{
  myTraceCutter->set_min_cutting_time( minCutTime );
}

void TraceCutterProxy::set_max_cutting_time( unsigned long long maxCutTime )
{
  myTraceCutter->set_min_cutting_time( maxCutTime );
}

void TraceCutterProxy::set_minimum_time_percentage( unsigned long long minimumPercentage )
{
  myTraceCutter->set_minimum_time_percentage( minimumPercentage );
}

void TraceCutterProxy::set_maximum_time_percentage( unsigned long long maximumPercentage )
{
  myTraceCutter->set_maximum_time_percentage( maximumPercentage );
}

void TraceCutterProxy::set_tasks_list( char *tasksList )
{
  myTraceCutter->set_tasks_list( tasksList );
}

void TraceCutterProxy::set_original_time( bool originalTime )
{
  myTraceCutter->set_original_time ( originalTime );
}

void TraceCutterProxy::set_max_trace_size( int traceSize )
{
  myTraceCutter->set_max_trace_size( traceSize );
}

void TraceCutterProxy::set_break_states( bool breakStates )
{
  myTraceCutter->set_break_states( breakStates );
}

void TraceCutterProxy::set_remFirstStates( bool remStates )
{
  myTraceCutter->set_remFirstStates ( remStates );
}

void TraceCutterProxy::set_remLastStates( bool remStates )
{
  myTraceCutter->set_remLastStates( remStates );
}

void TraceCutterProxy::set_keep_events( bool keepEvents )
{
  myTraceCutter->set_keep_events( keepEvents );
}

void TraceCutterProxy::setCutterApplicationCaller( std::string caller )
{
  myTraceCutter->setCutterApplicationCaller( caller );
}

<commit_msg>*** empty log message ***<commit_after>/*****************************************************************************\
 *                        ANALYSIS PERFORMANCE TOOLS                         *
 *                               libparaver-api                              *
 *                      API Library for libparaver-kernel                    *
 *****************************************************************************
 *     ___     This library is free software; you can redistribute it and/or *
 *    /  __         modify it under the terms of the GNU LGPL as published   *
 *   /  /  _____    by the Free Software Foundation; either version 2.1      *
 *  /  /  /     \   of the License, or (at your option) any later version.   *
 * (  (  ( B S C )                                                           *
 *  \  \  \_____/   This library is distributed in hope that it will be      *
 *   \  \__         useful but WITHOUT ANY WARRANTY; without even the        *
 *    \___          implied warranty of MERCHANTABILITY or FITNESS FOR A     *
 *                  PARTICULAR PURPOSE. See the GNU LGPL for more details.   *
 *                                                                           *
 * You should have received a copy of the GNU Lesser General Public License  *
 * along with this library; if not, write to the Free Software Foundation,   *
 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA          *
 * The GNU LEsser General Public License is contained in the file COPYING.   *
 *                                 ---------                                 *
 *   Barcelona Supercomputing Center - Centro Nacional de Supercomputacion   *
\*****************************************************************************/

/* -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- *\
 | @file: $HeadURL$
 | @last_commit: $Date$
 | @version:     $Revision$
\* -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */

#include "tracecutter.h"
//#include "ktraceoptions.h"
#include "traceoptions.h"
//#include "ktracecutter.h"
#include "kernelconnection.h"
#include "pcfparser/ParaverTraceConfig.h"
using namespace libparaver;
#include <map>
#include <string.h>
#include "eventlabels.h"

using namespace std;

string TraceCutter::traceToolID = "cutter";
string TraceCutter::traceToolName = "Cutter";
string TraceCutter::traceToolExtension = "chop";

TraceCutter *TraceCutter::create(  KernelConnection *whichKernel,
                                   char *traceIn,
                                   char *traceOut,
                                   TraceOptions *options,
                                   ProgressController *progress )
{
  return new TraceCutterProxy( whichKernel, traceIn, traceOut, options, progress );
}

TraceCutterProxy::TraceCutterProxy( const KernelConnection *whichKernel,
                                    char *traceIn,
                                    char *traceOut,
                                    TraceOptions *options,
                                    ProgressController *progress )
{
//  char *pcf_name, *c;
  std::string pcf_name;
  FILE *pcfFile;
  vector< TEventType > typesWithValueZero;
  struct stat tmpStatBuffer;

/*  pcf_name = strdup( traceIn );
  c = strrchr( pcf_name, '.' );
  sprintf( c, ".pcf" );*/

  pcf_name = LocalKernel::composeName( traceIn, string( "pcf" ) );
  stat( pcf_name.c_str(), &tmpStatBuffer );

  if( tmpStatBuffer.st_size > 0 )
  {
    ParaverTraceConfig *config = new ParaverTraceConfig( pcf_name );
    EventLabels myEventLabels = EventLabels( *config, set<TEventType>() );
    vector< TEventType > allTypes;
    EventLabels labels;
    labels.getTypes( allTypes );
    map< TEventValue, string > currentEventValues;
    for( vector< TEventType >::iterator it = allTypes.begin(); it != allTypes.end(); ++it )
    {
      if ( labels.getValues( *it, currentEventValues ) )
      {
        if ( currentEventValues.find( TEventValue( 0 )) != currentEventValues.end() )
        {
          typesWithValueZero.push_back( *it );
        }
        currentEventValues.clear();
      }
    }

    delete config;
  }

  myTraceCutter = whichKernel->newTraceCutter( options, typesWithValueZero );
  myTraceCutter->execute( traceIn, traceOut, progress );
}

TraceCutterProxy::~TraceCutterProxy()
{
  delete myTraceCutter;
}

void TraceCutterProxy::execute( char *trace_in, char *trace_out, ProgressController *progress )
{
  myTraceCutter->execute( trace_in, trace_out, progress );
}

void TraceCutterProxy::set_by_time( bool whichByTime )
{
  myTraceCutter->set_by_time( whichByTime );
}

void TraceCutterProxy::set_min_cutting_time( unsigned long long minCutTime )
{
  myTraceCutter->set_min_cutting_time( minCutTime );
}

void TraceCutterProxy::set_max_cutting_time( unsigned long long maxCutTime )
{
  myTraceCutter->set_min_cutting_time( maxCutTime );
}

void TraceCutterProxy::set_minimum_time_percentage( unsigned long long minimumPercentage )
{
  myTraceCutter->set_minimum_time_percentage( minimumPercentage );
}

void TraceCutterProxy::set_maximum_time_percentage( unsigned long long maximumPercentage )
{
  myTraceCutter->set_maximum_time_percentage( maximumPercentage );
}

void TraceCutterProxy::set_tasks_list( char *tasksList )
{
  myTraceCutter->set_tasks_list( tasksList );
}

void TraceCutterProxy::set_original_time( bool originalTime )
{
  myTraceCutter->set_original_time ( originalTime );
}

void TraceCutterProxy::set_max_trace_size( int traceSize )
{
  myTraceCutter->set_max_trace_size( traceSize );
}

void TraceCutterProxy::set_break_states( bool breakStates )
{
  myTraceCutter->set_break_states( breakStates );
}

void TraceCutterProxy::set_remFirstStates( bool remStates )
{
  myTraceCutter->set_remFirstStates ( remStates );
}

void TraceCutterProxy::set_remLastStates( bool remStates )
{
  myTraceCutter->set_remLastStates( remStates );
}

void TraceCutterProxy::set_keep_events( bool keepEvents )
{
  myTraceCutter->set_keep_events( keepEvents );
}

void TraceCutterProxy::setCutterApplicationCaller( std::string caller )
{
  myTraceCutter->setCutterApplicationCaller( caller );
}

<|endoftext|>


<commit_before>// Copyright (c) 2014 GitHub, Inc.
// Use of this source code is governed by the MIT license that can be
// found in the LICENSE file.

#include "atom/common/asar/archive.h"

#include <string>
#include <vector>

#include "atom/common/asar/scoped_temporary_file.h"
#include "base/files/file.h"
#include "base/files/file_util.h"
#include "base/json/json_reader.h"
#include "base/logging.h"
#include "base/pickle.h"
#include "base/strings/string_number_conversions.h"
#include "base/task_scheduler/post_task.h"
#include "base/threading/thread_restrictions.h"
#include "base/values.h"

#if defined(OS_WIN)
#include <io.h>
#endif

namespace asar {

namespace {

#if defined(OS_WIN)
const char kSeparators[] = "\\/";
#else
const char kSeparators[] = "/";
#endif

bool GetNodeFromPath(std::string path,
                     const base::DictionaryValue* root,
                     const base::DictionaryValue** out);

// Gets the "files" from "dir".
bool GetFilesNode(const base::DictionaryValue* root,
                  const base::DictionaryValue* dir,
                  const base::DictionaryValue** out) {
  // Test for symbol linked directory.
  std::string link;
  if (dir->GetStringWithoutPathExpansion("link", &link)) {
    const base::DictionaryValue* linked_node = nullptr;
    if (!GetNodeFromPath(link, root, &linked_node))
      return false;
    dir = linked_node;
  }

  return dir->GetDictionaryWithoutPathExpansion("files", out);
}

// Gets sub-file "name" from "dir".
bool GetChildNode(const base::DictionaryValue* root,
                  const std::string& name,
                  const base::DictionaryValue* dir,
                  const base::DictionaryValue** out) {
  if (name == "") {
    *out = root;
    return true;
  }

  const base::DictionaryValue* files = nullptr;
  return GetFilesNode(root, dir, &files) &&
         files->GetDictionaryWithoutPathExpansion(name, out);
}

// Gets the node of "path" from "root".
bool GetNodeFromPath(std::string path,
                     const base::DictionaryValue* root,
                     const base::DictionaryValue** out) {
  if (path == "") {
    *out = root;
    return true;
  }

  const base::DictionaryValue* dir = root;
  for (size_t delimiter_position = path.find_first_of(kSeparators);
       delimiter_position != std::string::npos;
       delimiter_position = path.find_first_of(kSeparators)) {
    const base::DictionaryValue* child = nullptr;
    if (!GetChildNode(root, path.substr(0, delimiter_position), dir, &child))
      return false;

    dir = child;
    path.erase(0, delimiter_position + 1);
  }

  return GetChildNode(root, path, dir, out);
}

bool FillFileInfoWithNode(Archive::FileInfo* info,
                          uint32_t header_size,
                          const base::DictionaryValue* node) {
  int size;
  if (!node->GetInteger("size", &size))
    return false;
  info->size = static_cast<uint32_t>(size);

  if (node->GetBoolean("unpacked", &info->unpacked) && info->unpacked)
    return true;

  std::string offset;
  if (!node->GetString("offset", &offset))
    return false;
  if (!base::StringToUint64(offset, &info->offset))
    return false;
  info->offset += header_size;

  node->GetBoolean("executable", &info->executable);

  return true;
}

}  // namespace

Archive::Archive(const base::FilePath& path)
    : path_(path), file_(base::File::FILE_OK), header_size_(0) {
  {
    base::ThreadRestrictions::ScopedAllowIO allow_io;
    file_.Initialize(path_, base::File::FLAG_OPEN | base::File::FLAG_READ);
#if defined(OS_WIN)
    fd_ =
        _open_osfhandle(reinterpret_cast<intptr_t>(file_.GetPlatformFile()), 0);
#elif defined(OS_POSIX)
    fd_ = file_.GetPlatformFile();
#else
    fd_ = -1;
#endif
  }
}

Archive::~Archive() {
#if defined(OS_WIN)
  if (fd_ != -1) {
    _close(fd_);
    // Don't close the handle since we already closed the fd.
    file_.TakePlatformFile();
  }
#endif
  base::PostTaskWithTraits(
      FROM_HERE,
      {base::MayBlock(), base::TaskPriority::BACKGROUND,
       base::TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN},
      base::Bind([](base::File file) { file.Close(); }, Passed(&file_)));
}

bool Archive::Init() {
  if (!file_.IsValid()) {
    if (file_.error_details() != base::File::FILE_ERROR_NOT_FOUND) {
      LOG(WARNING) << "Opening " << path_.value()
                   << ": " << base::File::ErrorToString(file_.error_details());
    }
    return false;
  }

  std::vector<char> buf;
  int len;

  buf.resize(8);
  {
    base::ThreadRestrictions::ScopedAllowIO allow_io;
    len = file_.ReadAtCurrentPos(buf.data(), buf.size());
  }
  if (len != static_cast<int>(buf.size())) {
    PLOG(ERROR) << "Failed to read header size from " << path_.value();
    return false;
  }

  uint32_t size;
  if (!base::PickleIterator(base::Pickle(buf.data(), buf.size())).ReadUInt32(
          &size)) {
    LOG(ERROR) << "Failed to parse header size from " << path_.value();
    return false;
  }

  buf.resize(size);
  {
    base::ThreadRestrictions::ScopedAllowIO allow_io;
    len = file_.ReadAtCurrentPos(buf.data(), buf.size());
  }
  if (len != static_cast<int>(buf.size())) {
    PLOG(ERROR) << "Failed to read header from " << path_.value();
    return false;
  }

  std::string header;
  if (!base::PickleIterator(base::Pickle(buf.data(), buf.size())).ReadString(
        &header)) {
    LOG(ERROR) << "Failed to parse header from " << path_.value();
    return false;
  }

  std::string error;
  base::JSONReader reader;
  std::unique_ptr<base::Value> value(reader.ReadToValue(header));
  if (!value || !value->IsType(base::Value::Type::DICTIONARY)) {
    LOG(ERROR) << "Failed to parse header: " << error;
    return false;
  }

  header_size_ = 8 + size;
  header_.reset(static_cast<base::DictionaryValue*>(value.release()));
  return true;
}

bool Archive::GetFileInfo(const base::FilePath& path, FileInfo* info) {
  if (!header_)
    return false;

  const base::DictionaryValue* node;
  if (!GetNodeFromPath(path.AsUTF8Unsafe(), header_.get(), &node))
    return false;

  std::string link;
  if (node->GetString("link", &link))
    return GetFileInfo(base::FilePath::FromUTF8Unsafe(link), info);

  return FillFileInfoWithNode(info, header_size_, node);
}

bool Archive::Stat(const base::FilePath& path, Stats* stats) {
  if (!header_)
    return false;

  const base::DictionaryValue* node;
  if (!GetNodeFromPath(path.AsUTF8Unsafe(), header_.get(), &node))
    return false;

  if (node->HasKey("link")) {
    stats->is_file = false;
    stats->is_link = true;
    return true;
  }

  if (node->HasKey("files")) {
    stats->is_file = false;
    stats->is_directory = true;
    return true;
  }

  return FillFileInfoWithNode(stats, header_size_, node);
}

bool Archive::Readdir(const base::FilePath& path,
                      std::vector<base::FilePath>* list) {
  if (!header_)
    return false;

  const base::DictionaryValue* node;
  if (!GetNodeFromPath(path.AsUTF8Unsafe(), header_.get(), &node))
    return false;

  const base::DictionaryValue* files;
  if (!GetFilesNode(header_.get(), node, &files))
    return false;

  base::DictionaryValue::Iterator iter(*files);
  while (!iter.IsAtEnd()) {
    list->push_back(base::FilePath::FromUTF8Unsafe(iter.key()));
    iter.Advance();
  }
  return true;
}

bool Archive::Realpath(const base::FilePath& path, base::FilePath* realpath) {
  if (!header_)
    return false;

  const base::DictionaryValue* node;
  if (!GetNodeFromPath(path.AsUTF8Unsafe(), header_.get(), &node))
    return false;

  std::string link;
  if (node->GetString("link", &link)) {
    *realpath = base::FilePath::FromUTF8Unsafe(link);
    return true;
  }

  *realpath = path;
  return true;
}

bool Archive::CopyFileOut(const base::FilePath& path, base::FilePath* out) {
  auto it = external_files_.find(path.value());
  if (it != external_files_.end()) {
    *out = it->second->path();
    return true;
  }

  FileInfo info;
  if (!GetFileInfo(path, &info))
    return false;

  if (info.unpacked) {
    *out = path_.AddExtension(FILE_PATH_LITERAL("unpacked")).Append(path);
    return true;
  }

  std::unique_ptr<ScopedTemporaryFile> temp_file(new ScopedTemporaryFile);
  base::FilePath::StringType ext = path.Extension();
  if (!temp_file->InitFromFile(&file_, ext, info.offset, info.size))
    return false;

#if defined(OS_POSIX)
  if (info.executable) {
    // chmod a+x temp_file;
    base::SetPosixFilePermissions(temp_file->path(), 0755);
  }
#endif

  *out = temp_file->path();
  external_files_[path.value()] = std::move(temp_file);
  return true;
}

int Archive::GetFD() const {
  return fd_;
}

}  // namespace asar
<commit_msg>Remove unnecessary scope<commit_after>// Copyright (c) 2014 GitHub, Inc.
// Use of this source code is governed by the MIT license that can be
// found in the LICENSE file.

#include "atom/common/asar/archive.h"

#include <string>
#include <vector>

#include "atom/common/asar/scoped_temporary_file.h"
#include "base/files/file.h"
#include "base/files/file_util.h"
#include "base/json/json_reader.h"
#include "base/logging.h"
#include "base/pickle.h"
#include "base/strings/string_number_conversions.h"
#include "base/task_scheduler/post_task.h"
#include "base/threading/thread_restrictions.h"
#include "base/values.h"

#if defined(OS_WIN)
#include <io.h>
#endif

namespace asar {

namespace {

#if defined(OS_WIN)
const char kSeparators[] = "\\/";
#else
const char kSeparators[] = "/";
#endif

bool GetNodeFromPath(std::string path,
                     const base::DictionaryValue* root,
                     const base::DictionaryValue** out);

// Gets the "files" from "dir".
bool GetFilesNode(const base::DictionaryValue* root,
                  const base::DictionaryValue* dir,
                  const base::DictionaryValue** out) {
  // Test for symbol linked directory.
  std::string link;
  if (dir->GetStringWithoutPathExpansion("link", &link)) {
    const base::DictionaryValue* linked_node = nullptr;
    if (!GetNodeFromPath(link, root, &linked_node))
      return false;
    dir = linked_node;
  }

  return dir->GetDictionaryWithoutPathExpansion("files", out);
}

// Gets sub-file "name" from "dir".
bool GetChildNode(const base::DictionaryValue* root,
                  const std::string& name,
                  const base::DictionaryValue* dir,
                  const base::DictionaryValue** out) {
  if (name == "") {
    *out = root;
    return true;
  }

  const base::DictionaryValue* files = nullptr;
  return GetFilesNode(root, dir, &files) &&
         files->GetDictionaryWithoutPathExpansion(name, out);
}

// Gets the node of "path" from "root".
bool GetNodeFromPath(std::string path,
                     const base::DictionaryValue* root,
                     const base::DictionaryValue** out) {
  if (path == "") {
    *out = root;
    return true;
  }

  const base::DictionaryValue* dir = root;
  for (size_t delimiter_position = path.find_first_of(kSeparators);
       delimiter_position != std::string::npos;
       delimiter_position = path.find_first_of(kSeparators)) {
    const base::DictionaryValue* child = nullptr;
    if (!GetChildNode(root, path.substr(0, delimiter_position), dir, &child))
      return false;

    dir = child;
    path.erase(0, delimiter_position + 1);
  }

  return GetChildNode(root, path, dir, out);
}

bool FillFileInfoWithNode(Archive::FileInfo* info,
                          uint32_t header_size,
                          const base::DictionaryValue* node) {
  int size;
  if (!node->GetInteger("size", &size))
    return false;
  info->size = static_cast<uint32_t>(size);

  if (node->GetBoolean("unpacked", &info->unpacked) && info->unpacked)
    return true;

  std::string offset;
  if (!node->GetString("offset", &offset))
    return false;
  if (!base::StringToUint64(offset, &info->offset))
    return false;
  info->offset += header_size;

  node->GetBoolean("executable", &info->executable);

  return true;
}

}  // namespace

Archive::Archive(const base::FilePath& path)
    : path_(path), file_(base::File::FILE_OK), header_size_(0) {
  base::ThreadRestrictions::ScopedAllowIO allow_io;
  file_.Initialize(path_, base::File::FLAG_OPEN | base::File::FLAG_READ);
#if defined(OS_WIN)
  fd_ =
      _open_osfhandle(reinterpret_cast<intptr_t>(file_.GetPlatformFile()), 0);
#elif defined(OS_POSIX)
  fd_ = file_.GetPlatformFile();
#else
  fd_ = -1;
#endif
}

Archive::~Archive() {
#if defined(OS_WIN)
  if (fd_ != -1) {
    _close(fd_);
    // Don't close the handle since we already closed the fd.
    file_.TakePlatformFile();
  }
#endif
  base::PostTaskWithTraits(
      FROM_HERE,
      {base::MayBlock(), base::TaskPriority::BACKGROUND,
       base::TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN},
      base::Bind([](base::File file) { file.Close(); }, Passed(&file_)));
}

bool Archive::Init() {
  if (!file_.IsValid()) {
    if (file_.error_details() != base::File::FILE_ERROR_NOT_FOUND) {
      LOG(WARNING) << "Opening " << path_.value()
                   << ": " << base::File::ErrorToString(file_.error_details());
    }
    return false;
  }

  std::vector<char> buf;
  int len;

  buf.resize(8);
  {
    base::ThreadRestrictions::ScopedAllowIO allow_io;
    len = file_.ReadAtCurrentPos(buf.data(), buf.size());
  }
  if (len != static_cast<int>(buf.size())) {
    PLOG(ERROR) << "Failed to read header size from " << path_.value();
    return false;
  }

  uint32_t size;
  if (!base::PickleIterator(base::Pickle(buf.data(), buf.size())).ReadUInt32(
          &size)) {
    LOG(ERROR) << "Failed to parse header size from " << path_.value();
    return false;
  }

  buf.resize(size);
  {
    base::ThreadRestrictions::ScopedAllowIO allow_io;
    len = file_.ReadAtCurrentPos(buf.data(), buf.size());
  }
  if (len != static_cast<int>(buf.size())) {
    PLOG(ERROR) << "Failed to read header from " << path_.value();
    return false;
  }

  std::string header;
  if (!base::PickleIterator(base::Pickle(buf.data(), buf.size())).ReadString(
        &header)) {
    LOG(ERROR) << "Failed to parse header from " << path_.value();
    return false;
  }

  std::string error;
  base::JSONReader reader;
  std::unique_ptr<base::Value> value(reader.ReadToValue(header));
  if (!value || !value->IsType(base::Value::Type::DICTIONARY)) {
    LOG(ERROR) << "Failed to parse header: " << error;
    return false;
  }

  header_size_ = 8 + size;
  header_.reset(static_cast<base::DictionaryValue*>(value.release()));
  return true;
}

bool Archive::GetFileInfo(const base::FilePath& path, FileInfo* info) {
  if (!header_)
    return false;

  const base::DictionaryValue* node;
  if (!GetNodeFromPath(path.AsUTF8Unsafe(), header_.get(), &node))
    return false;

  std::string link;
  if (node->GetString("link", &link))
    return GetFileInfo(base::FilePath::FromUTF8Unsafe(link), info);

  return FillFileInfoWithNode(info, header_size_, node);
}

bool Archive::Stat(const base::FilePath& path, Stats* stats) {
  if (!header_)
    return false;

  const base::DictionaryValue* node;
  if (!GetNodeFromPath(path.AsUTF8Unsafe(), header_.get(), &node))
    return false;

  if (node->HasKey("link")) {
    stats->is_file = false;
    stats->is_link = true;
    return true;
  }

  if (node->HasKey("files")) {
    stats->is_file = false;
    stats->is_directory = true;
    return true;
  }

  return FillFileInfoWithNode(stats, header_size_, node);
}

bool Archive::Readdir(const base::FilePath& path,
                      std::vector<base::FilePath>* list) {
  if (!header_)
    return false;

  const base::DictionaryValue* node;
  if (!GetNodeFromPath(path.AsUTF8Unsafe(), header_.get(), &node))
    return false;

  const base::DictionaryValue* files;
  if (!GetFilesNode(header_.get(), node, &files))
    return false;

  base::DictionaryValue::Iterator iter(*files);
  while (!iter.IsAtEnd()) {
    list->push_back(base::FilePath::FromUTF8Unsafe(iter.key()));
    iter.Advance();
  }
  return true;
}

bool Archive::Realpath(const base::FilePath& path, base::FilePath* realpath) {
  if (!header_)
    return false;

  const base::DictionaryValue* node;
  if (!GetNodeFromPath(path.AsUTF8Unsafe(), header_.get(), &node))
    return false;

  std::string link;
  if (node->GetString("link", &link)) {
    *realpath = base::FilePath::FromUTF8Unsafe(link);
    return true;
  }

  *realpath = path;
  return true;
}

bool Archive::CopyFileOut(const base::FilePath& path, base::FilePath* out) {
  auto it = external_files_.find(path.value());
  if (it != external_files_.end()) {
    *out = it->second->path();
    return true;
  }

  FileInfo info;
  if (!GetFileInfo(path, &info))
    return false;

  if (info.unpacked) {
    *out = path_.AddExtension(FILE_PATH_LITERAL("unpacked")).Append(path);
    return true;
  }

  std::unique_ptr<ScopedTemporaryFile> temp_file(new ScopedTemporaryFile);
  base::FilePath::StringType ext = path.Extension();
  if (!temp_file->InitFromFile(&file_, ext, info.offset, info.size))
    return false;

#if defined(OS_POSIX)
  if (info.executable) {
    // chmod a+x temp_file;
    base::SetPosixFilePermissions(temp_file->path(), 0755);
  }
#endif

  *out = temp_file->path();
  external_files_[path.value()] = std::move(temp_file);
  return true;
}

int Archive::GetFD() const {
  return fd_;
}

}  // namespace asar
<|endoftext|>