<commit_before>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: AResultSetMetaData.hxx,v $
 *
 *  $Revision: 1.5 $
 *
 *  last change: $Author: kz $ $Date: 2006-11-06 14:35:24 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/

#ifndef _CONNECTIVITY_ADO_ARESULTSETMETADATA_HXX_
#define _CONNECTIVITY_ADO_ARESULTSETMETADATA_HXX_

#ifndef _COM_SUN_STAR_SDBC_XRESULTSETMETADATA_HPP_
#include <com/sun/star/sdbc/XResultSetMetaData.hpp>
#endif
#ifndef _CPPUHELPER_IMPLBASE1_HXX_
#include <cppuhelper/implbase1.hxx>
#endif
#ifndef _VECTOR_
#include <vector>
#endif

#ifndef _CONNECTIVITY_ADO_AWRAPADO_HXX_
#include "ado/Awrapado.hxx"
#endif
#ifndef _CONNECTIVITY_ADO_ARESULTSET_HXX_
#include "ado/AResultSet.hxx"
#endif
#ifndef _CONNECTIVITY_COLUMN_HXX_
#include "OColumn.hxx"
#endif

namespace connectivity
{
    namespace ado
    {

        //**************************************************************
        //************ Class: ResultSetMetaData
        //**************************************************************
                typedef ::cppu::WeakImplHelper1<        ::com::sun::star::sdbc::XResultSetMetaData>   OResultSetMetaData_BASE;

        class OResultSetMetaData :  public  OResultSetMetaData_BASE
        {
            friend class OResultSet;

            ADORecordset*   m_pRecordSet;
            sal_Int32       m_nColCount;

            sal_Int32 MapADOType2Jdbc(DataTypeEnum eType);
        private:
            OResultSetMetaData( const OResultSetMetaData& );            // never implemented
            OResultSetMetaData& operator=( const OResultSetMetaData& ); // never implemented

        protected:
            virtual ~OResultSetMetaData();
        public:
            // ein Konstruktor, der fuer das Returnen des Objektes benoetigt wird:
            OResultSetMetaData( ADORecordset* _pRecordSet);

            virtual sal_Int32 SAL_CALL getColumnCount(  ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException);
            virtual sal_Bool SAL_CALL isAutoIncrement( sal_Int32 column ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException);
            virtual sal_Bool SAL_CALL isCaseSensitive( sal_Int32 column ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException);
            virtual sal_Bool SAL_CALL isSearchable( sal_Int32 column ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException);
            virtual sal_Bool SAL_CALL isCurrency( sal_Int32 column ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException);
            virtual sal_Int32 SAL_CALL isNullable( sal_Int32 column ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException);
            virtual sal_Bool SAL_CALL isSigned( sal_Int32 column ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException);
            virtual sal_Int32 SAL_CALL getColumnDisplaySize( sal_Int32 column ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException);
            virtual ::rtl::OUString SAL_CALL getColumnLabel( sal_Int32 column ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException);
            virtual ::rtl::OUString SAL_CALL getColumnName( sal_Int32 column ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException);
            virtual ::rtl::OUString SAL_CALL getSchemaName( sal_Int32 column ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException);
            virtual sal_Int32 SAL_CALL getPrecision( sal_Int32 column ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException);
            virtual sal_Int32 SAL_CALL getScale( sal_Int32 column ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException);
            virtual ::rtl::OUString SAL_CALL getTableName( sal_Int32 column ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException);
            virtual ::rtl::OUString SAL_CALL getCatalogName( sal_Int32 column ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException);
            virtual sal_Int32 SAL_CALL getColumnType( sal_Int32 column ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException);
            virtual ::rtl::OUString SAL_CALL getColumnTypeName( sal_Int32 column ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException);
            virtual sal_Bool SAL_CALL isReadOnly( sal_Int32 column ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException);
            virtual sal_Bool SAL_CALL isWritable( sal_Int32 column ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException);
            virtual sal_Bool SAL_CALL isDefinitelyWritable( sal_Int32 column ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException);
            virtual ::rtl::OUString SAL_CALL getColumnServiceName( sal_Int32 column ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException);
        };
    }
}
#endif // _CONNECTIVITY_ADO_ARESULTSETMETADATA_HXX_

<commit_msg>INTEGRATION: CWS changefileheader (1.5.190); FILE MERGED 2008/04/01 15:09:09 thb 1.5.190.3: #i85898# Stripping all external header guards 2008/04/01 10:53:21 thb 1.5.190.2: #i85898# Stripping all external header guards 2008/03/28 15:24:12 rt 1.5.190.1: #i87441# Change license header to LPGL v3.<commit_after>/*************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2008 by Sun Microsystems, Inc.
 *
 * OpenOffice.org - a multi-platform office productivity suite
 *
 * $RCSfile: AResultSetMetaData.hxx,v $
 * $Revision: 1.6 $
 *
 * This file is part of OpenOffice.org.
 *
 * OpenOffice.org is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License version 3
 * only, as published by the Free Software Foundation.
 *
 * OpenOffice.org 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 version 3 for more details
 * (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU Lesser General Public License
 * version 3 along with OpenOffice.org.  If not, see
 * <http://www.openoffice.org/license.html>
 * for a copy of the LGPLv3 License.
 *
 ************************************************************************/

#ifndef _CONNECTIVITY_ADO_ARESULTSETMETADATA_HXX_
#define _CONNECTIVITY_ADO_ARESULTSETMETADATA_HXX_

#include <com/sun/star/sdbc/XResultSetMetaData.hpp>
#include <cppuhelper/implbase1.hxx>
#ifndef _VECTOR_
#include <vector>
#endif
#include "ado/Awrapado.hxx"
#include "ado/AResultSet.hxx"
#include "OColumn.hxx"

namespace connectivity
{
    namespace ado
    {

        //**************************************************************
        //************ Class: ResultSetMetaData
        //**************************************************************
                typedef ::cppu::WeakImplHelper1<        ::com::sun::star::sdbc::XResultSetMetaData>   OResultSetMetaData_BASE;

        class OResultSetMetaData :  public  OResultSetMetaData_BASE
        {
            friend class OResultSet;

            ADORecordset*   m_pRecordSet;
            sal_Int32       m_nColCount;

            sal_Int32 MapADOType2Jdbc(DataTypeEnum eType);
        private:
            OResultSetMetaData( const OResultSetMetaData& );            // never implemented
            OResultSetMetaData& operator=( const OResultSetMetaData& ); // never implemented

        protected:
            virtual ~OResultSetMetaData();
        public:
            // ein Konstruktor, der fuer das Returnen des Objektes benoetigt wird:
            OResultSetMetaData( ADORecordset* _pRecordSet);

            virtual sal_Int32 SAL_CALL getColumnCount(  ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException);
            virtual sal_Bool SAL_CALL isAutoIncrement( sal_Int32 column ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException);
            virtual sal_Bool SAL_CALL isCaseSensitive( sal_Int32 column ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException);
            virtual sal_Bool SAL_CALL isSearchable( sal_Int32 column ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException);
            virtual sal_Bool SAL_CALL isCurrency( sal_Int32 column ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException);
            virtual sal_Int32 SAL_CALL isNullable( sal_Int32 column ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException);
            virtual sal_Bool SAL_CALL isSigned( sal_Int32 column ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException);
            virtual sal_Int32 SAL_CALL getColumnDisplaySize( sal_Int32 column ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException);
            virtual ::rtl::OUString SAL_CALL getColumnLabel( sal_Int32 column ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException);
            virtual ::rtl::OUString SAL_CALL getColumnName( sal_Int32 column ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException);
            virtual ::rtl::OUString SAL_CALL getSchemaName( sal_Int32 column ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException);
            virtual sal_Int32 SAL_CALL getPrecision( sal_Int32 column ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException);
            virtual sal_Int32 SAL_CALL getScale( sal_Int32 column ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException);
            virtual ::rtl::OUString SAL_CALL getTableName( sal_Int32 column ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException);
            virtual ::rtl::OUString SAL_CALL getCatalogName( sal_Int32 column ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException);
            virtual sal_Int32 SAL_CALL getColumnType( sal_Int32 column ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException);
            virtual ::rtl::OUString SAL_CALL getColumnTypeName( sal_Int32 column ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException);
            virtual sal_Bool SAL_CALL isReadOnly( sal_Int32 column ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException);
            virtual sal_Bool SAL_CALL isWritable( sal_Int32 column ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException);
            virtual sal_Bool SAL_CALL isDefinitelyWritable( sal_Int32 column ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException);
            virtual ::rtl::OUString SAL_CALL getColumnServiceName( sal_Int32 column ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException);
        };
    }
}
#endif // _CONNECTIVITY_ADO_ARESULTSETMETADATA_HXX_

<|endoftext|>


<commit_before>// Copyright (c) 2012 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/message_loop.h"
#include "base/string_number_conversions.h"
#include "content/browser/browser_thread_impl.h"
#include "content/browser/download/download_create_info.h"
#include "content/browser/download/download_file_impl.h"
#include "content/browser/download/download_request_handle.h"
#include "content/public/browser/download_manager.h"
#include "content/test/mock_download_manager.h"
#include "net/base/file_stream.h"
#include "net/base/net_errors.h"
#include "testing/gtest/include/gtest/gtest.h"

using content::BrowserThread;
using content::BrowserThreadImpl;
using content::DownloadFile;
using content::DownloadId;
using content::DownloadManager;

DownloadId::Domain kValidIdDomain = "valid DownloadId::Domain";

class DownloadFileTest : public testing::Test {
 public:

  static const char* kTestData1;
  static const char* kTestData2;
  static const char* kTestData3;
  static const char* kDataHash;
  static const int32 kDummyDownloadId;
  static const int kDummyChildId;
  static const int kDummyRequestId;

  // We need a UI |BrowserThread| in order to destruct |download_manager_|,
  // which has trait |BrowserThread::DeleteOnUIThread|.  Without this,
  // calling Release() on |download_manager_| won't ever result in its
  // destructor being called and we get a leak.
  DownloadFileTest() :
      ui_thread_(BrowserThread::UI, &loop_),
      file_thread_(BrowserThread::FILE, &loop_) {
  }

  ~DownloadFileTest() {
  }

  virtual void SetUp() {
    download_manager_ = new content::MockDownloadManager;
  }

  virtual void TearDown() {
    // When a DownloadManager's reference count drops to 0, it is not
    // deleted immediately. Instead, a task is posted to the UI thread's
    // message loop to delete it.
    // So, drop the reference count to 0 and run the message loop once
    // to ensure that all resources are cleaned up before the test exits.
    download_manager_ = NULL;
    ui_thread_.message_loop()->RunAllPending();
  }

  virtual void CreateDownloadFile(scoped_ptr<DownloadFile>* file,
                                  int offset,
                                  bool calculate_hash) {
    DownloadCreateInfo info;
    info.download_id = DownloadId(kValidIdDomain, kDummyDownloadId + offset);
    // info.request_handle default constructed to null.
    info.save_info.file_stream = file_stream_;
    file->reset(
        new DownloadFileImpl(&info, new DownloadRequestHandle(),
                             download_manager_, calculate_hash,
                             net::BoundNetLog()));
  }

  virtual void DestroyDownloadFile(scoped_ptr<DownloadFile>* file, int offset) {
    EXPECT_EQ(kDummyDownloadId + offset, (*file)->Id());
    EXPECT_EQ(download_manager_, (*file)->GetDownloadManager());
    EXPECT_FALSE((*file)->InProgress());
    EXPECT_EQ(static_cast<int64>(expected_data_.size()),
              (*file)->BytesSoFar());

    // Make sure the data has been properly written to disk.
    std::string disk_data;
    EXPECT_TRUE(file_util::ReadFileToString((*file)->FullPath(),
                                            &disk_data));
    EXPECT_EQ(expected_data_, disk_data);

    // Make sure the Browser and File threads outlive the DownloadFile
    // to satisfy thread checks inside it.
    file->reset();
  }

  void AppendDataToFile(scoped_ptr<DownloadFile>* file,
                        const std::string& data) {
    EXPECT_TRUE((*file)->InProgress());
    (*file)->AppendDataToFile(data.data(), data.size());
    expected_data_ += data;
    EXPECT_EQ(static_cast<int64>(expected_data_.size()),
              (*file)->BytesSoFar());
  }

 protected:
  scoped_refptr<DownloadManager> download_manager_;

  linked_ptr<net::FileStream> file_stream_;

  // DownloadFile instance we are testing.
  scoped_ptr<DownloadFile> download_file_;

 private:
  MessageLoop loop_;
  // UI thread.
  BrowserThreadImpl ui_thread_;
  // File thread to satisfy debug checks in DownloadFile.
  BrowserThreadImpl file_thread_;

  // Keep track of what data should be saved to the disk file.
  std::string expected_data_;
};

const char* DownloadFileTest::kTestData1 =
    "Let's write some data to the file!\n";
const char* DownloadFileTest::kTestData2 = "Writing more data.\n";
const char* DownloadFileTest::kTestData3 = "Final line.";
const char* DownloadFileTest::kDataHash =
    "CBF68BF10F8003DB86B31343AFAC8C7175BD03FB5FC905650F8C80AF087443A8";

const int32 DownloadFileTest::kDummyDownloadId = 23;
const int DownloadFileTest::kDummyChildId = 3;
const int DownloadFileTest::kDummyRequestId = 67;

// Rename the file before any data is downloaded, after some has, after it all
// has, and after it's closed.
TEST_F(DownloadFileTest, RenameFileFinal) {
  CreateDownloadFile(&download_file_, 0, true);
  ASSERT_EQ(net::OK, download_file_->Initialize());
  FilePath initial_path(download_file_->FullPath());
  EXPECT_TRUE(file_util::PathExists(initial_path));
  FilePath path_1(initial_path.InsertBeforeExtensionASCII("_1"));
  FilePath path_2(initial_path.InsertBeforeExtensionASCII("_2"));
  FilePath path_3(initial_path.InsertBeforeExtensionASCII("_3"));
  FilePath path_4(initial_path.InsertBeforeExtensionASCII("_4"));

  // Rename the file before downloading any data.
  EXPECT_EQ(net::OK, download_file_->Rename(path_1));
  FilePath renamed_path = download_file_->FullPath();
  EXPECT_EQ(path_1, renamed_path);

  // Check the files.
  EXPECT_FALSE(file_util::PathExists(initial_path));
  EXPECT_TRUE(file_util::PathExists(path_1));

  // Download the data.
  AppendDataToFile(&download_file_, kTestData1);
  AppendDataToFile(&download_file_, kTestData2);

  // Rename the file after downloading some data.
  EXPECT_EQ(net::OK, download_file_->Rename(path_2));
  renamed_path = download_file_->FullPath();
  EXPECT_EQ(path_2, renamed_path);

  // Check the files.
  EXPECT_FALSE(file_util::PathExists(path_1));
  EXPECT_TRUE(file_util::PathExists(path_2));

  AppendDataToFile(&download_file_, kTestData3);

  // Rename the file after downloading all the data.
  EXPECT_EQ(net::OK, download_file_->Rename(path_3));
  renamed_path = download_file_->FullPath();
  EXPECT_EQ(path_3, renamed_path);

  // Check the files.
  EXPECT_FALSE(file_util::PathExists(path_2));
  EXPECT_TRUE(file_util::PathExists(path_3));

  // Should not be able to get the hash until the file is closed.
  std::string hash;
  EXPECT_FALSE(download_file_->GetHash(&hash));

  download_file_->Finish();

  // Rename the file after downloading all the data and closing the file.
  EXPECT_EQ(net::OK, download_file_->Rename(path_4));
  renamed_path = download_file_->FullPath();
  EXPECT_EQ(path_4, renamed_path);

  // Check the files.
  EXPECT_FALSE(file_util::PathExists(path_3));
  EXPECT_TRUE(file_util::PathExists(path_4));

  // Check the hash.
  EXPECT_TRUE(download_file_->GetHash(&hash));
  EXPECT_EQ(kDataHash, base::HexEncode(hash.data(), hash.size()));

  DestroyDownloadFile(&download_file_, 0);
}
<commit_msg>Disable crashing unit test on Linux.<commit_after>// Copyright (c) 2012 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/message_loop.h"
#include "base/string_number_conversions.h"
#include "content/browser/browser_thread_impl.h"
#include "content/browser/download/download_create_info.h"
#include "content/browser/download/download_file_impl.h"
#include "content/browser/download/download_request_handle.h"
#include "content/public/browser/download_manager.h"
#include "content/test/mock_download_manager.h"
#include "net/base/file_stream.h"
#include "net/base/net_errors.h"
#include "testing/gtest/include/gtest/gtest.h"

#if defined(OS_LINUX)
// http://crbug.com/110886 for Linux
#define MAYBE_RenameFileFinal DISABLED_RenameFileFinal
#else
#define MAYBE_RenameFileFinal RenameFileFinal
#endif

using content::BrowserThread;
using content::BrowserThreadImpl;
using content::DownloadFile;
using content::DownloadId;
using content::DownloadManager;

DownloadId::Domain kValidIdDomain = "valid DownloadId::Domain";

class DownloadFileTest : public testing::Test {
 public:

  static const char* kTestData1;
  static const char* kTestData2;
  static const char* kTestData3;
  static const char* kDataHash;
  static const int32 kDummyDownloadId;
  static const int kDummyChildId;
  static const int kDummyRequestId;

  // We need a UI |BrowserThread| in order to destruct |download_manager_|,
  // which has trait |BrowserThread::DeleteOnUIThread|.  Without this,
  // calling Release() on |download_manager_| won't ever result in its
  // destructor being called and we get a leak.
  DownloadFileTest() :
      ui_thread_(BrowserThread::UI, &loop_),
      file_thread_(BrowserThread::FILE, &loop_) {
  }

  ~DownloadFileTest() {
  }

  virtual void SetUp() {
    download_manager_ = new content::MockDownloadManager;
  }

  virtual void TearDown() {
    // When a DownloadManager's reference count drops to 0, it is not
    // deleted immediately. Instead, a task is posted to the UI thread's
    // message loop to delete it.
    // So, drop the reference count to 0 and run the message loop once
    // to ensure that all resources are cleaned up before the test exits.
    download_manager_ = NULL;
    ui_thread_.message_loop()->RunAllPending();
  }

  virtual void CreateDownloadFile(scoped_ptr<DownloadFile>* file,
                                  int offset,
                                  bool calculate_hash) {
    DownloadCreateInfo info;
    info.download_id = DownloadId(kValidIdDomain, kDummyDownloadId + offset);
    // info.request_handle default constructed to null.
    info.save_info.file_stream = file_stream_;
    file->reset(
        new DownloadFileImpl(&info, new DownloadRequestHandle(),
                             download_manager_, calculate_hash,
                             net::BoundNetLog()));
  }

  virtual void DestroyDownloadFile(scoped_ptr<DownloadFile>* file, int offset) {
    EXPECT_EQ(kDummyDownloadId + offset, (*file)->Id());
    EXPECT_EQ(download_manager_, (*file)->GetDownloadManager());
    EXPECT_FALSE((*file)->InProgress());
    EXPECT_EQ(static_cast<int64>(expected_data_.size()),
              (*file)->BytesSoFar());

    // Make sure the data has been properly written to disk.
    std::string disk_data;
    EXPECT_TRUE(file_util::ReadFileToString((*file)->FullPath(),
                                            &disk_data));
    EXPECT_EQ(expected_data_, disk_data);

    // Make sure the Browser and File threads outlive the DownloadFile
    // to satisfy thread checks inside it.
    file->reset();
  }

  void AppendDataToFile(scoped_ptr<DownloadFile>* file,
                        const std::string& data) {
    EXPECT_TRUE((*file)->InProgress());
    (*file)->AppendDataToFile(data.data(), data.size());
    expected_data_ += data;
    EXPECT_EQ(static_cast<int64>(expected_data_.size()),
              (*file)->BytesSoFar());
  }

 protected:
  scoped_refptr<DownloadManager> download_manager_;

  linked_ptr<net::FileStream> file_stream_;

  // DownloadFile instance we are testing.
  scoped_ptr<DownloadFile> download_file_;

 private:
  MessageLoop loop_;
  // UI thread.
  BrowserThreadImpl ui_thread_;
  // File thread to satisfy debug checks in DownloadFile.
  BrowserThreadImpl file_thread_;

  // Keep track of what data should be saved to the disk file.
  std::string expected_data_;
};

const char* DownloadFileTest::kTestData1 =
    "Let's write some data to the file!\n";
const char* DownloadFileTest::kTestData2 = "Writing more data.\n";
const char* DownloadFileTest::kTestData3 = "Final line.";
const char* DownloadFileTest::kDataHash =
    "CBF68BF10F8003DB86B31343AFAC8C7175BD03FB5FC905650F8C80AF087443A8";

const int32 DownloadFileTest::kDummyDownloadId = 23;
const int DownloadFileTest::kDummyChildId = 3;
const int DownloadFileTest::kDummyRequestId = 67;

// Rename the file before any data is downloaded, after some has, after it all
// has, and after it's closed.
TEST_F(DownloadFileTest, MAYBE_RenameFileFinal) {
  CreateDownloadFile(&download_file_, 0, true);
  ASSERT_EQ(net::OK, download_file_->Initialize());
  FilePath initial_path(download_file_->FullPath());
  EXPECT_TRUE(file_util::PathExists(initial_path));
  FilePath path_1(initial_path.InsertBeforeExtensionASCII("_1"));
  FilePath path_2(initial_path.InsertBeforeExtensionASCII("_2"));
  FilePath path_3(initial_path.InsertBeforeExtensionASCII("_3"));
  FilePath path_4(initial_path.InsertBeforeExtensionASCII("_4"));

  // Rename the file before downloading any data.
  EXPECT_EQ(net::OK, download_file_->Rename(path_1));
  FilePath renamed_path = download_file_->FullPath();
  EXPECT_EQ(path_1, renamed_path);

  // Check the files.
  EXPECT_FALSE(file_util::PathExists(initial_path));
  EXPECT_TRUE(file_util::PathExists(path_1));

  // Download the data.
  AppendDataToFile(&download_file_, kTestData1);
  AppendDataToFile(&download_file_, kTestData2);

  // Rename the file after downloading some data.
  EXPECT_EQ(net::OK, download_file_->Rename(path_2));
  renamed_path = download_file_->FullPath();
  EXPECT_EQ(path_2, renamed_path);

  // Check the files.
  EXPECT_FALSE(file_util::PathExists(path_1));
  EXPECT_TRUE(file_util::PathExists(path_2));

  AppendDataToFile(&download_file_, kTestData3);

  // Rename the file after downloading all the data.
  EXPECT_EQ(net::OK, download_file_->Rename(path_3));
  renamed_path = download_file_->FullPath();
  EXPECT_EQ(path_3, renamed_path);

  // Check the files.
  EXPECT_FALSE(file_util::PathExists(path_2));
  EXPECT_TRUE(file_util::PathExists(path_3));

  // Should not be able to get the hash until the file is closed.
  std::string hash;
  EXPECT_FALSE(download_file_->GetHash(&hash));

  download_file_->Finish();

  // Rename the file after downloading all the data and closing the file.
  EXPECT_EQ(net::OK, download_file_->Rename(path_4));
  renamed_path = download_file_->FullPath();
  EXPECT_EQ(path_4, renamed_path);

  // Check the files.
  EXPECT_FALSE(file_util::PathExists(path_3));
  EXPECT_TRUE(file_util::PathExists(path_4));

  // Check the hash.
  EXPECT_TRUE(download_file_->GetHash(&hash));
  EXPECT_EQ(kDataHash, base::HexEncode(hash.data(), hash.size()));

  DestroyDownloadFile(&download_file_, 0);
}
<|endoftext|>


<commit_before>#include "track_analyzing/track_analyzer/crossroad_checker.hpp"

#include "track_analyzing/track.hpp"
#include "track_analyzing/utils.hpp"

#include "routing/city_roads.hpp"
#include "routing/geometry.hpp"
#include "routing/index_graph.hpp"
#include "routing/index_graph_loader.hpp"
#include "routing/maxspeeds.hpp"

#include "routing_common/car_model.hpp"
#include "routing_common/maxspeed_conversion.hpp"
#include "routing_common/vehicle_model.hpp"

#include "traffic/speed_groups.hpp"

#include "indexer/classificator.hpp"
#include "indexer/data_source.hpp"
#include "indexer/feature.hpp"
#include "indexer/feature_data.hpp"
#include "indexer/features_vector.hpp"

#include "storage/routing_helpers.hpp"
#include "storage/storage.hpp"

#include "coding/file_reader.hpp"

#include "geometry/latlon.hpp"

#include "base/assert.hpp"
#include "base/file_name_utils.hpp"
#include "base/stl_helpers.hpp"
#include "base/sunrise_sunset.hpp"
#include "base/timer.hpp"

#include <algorithm>
#include <array>
#include <cstdint>
#include <iostream>
#include <limits>
#include <map>
#include <memory>
#include <sstream>
#include <string>
#include <tuple>
#include <utility>
#include <vector>

#include <boost/optional.hpp>

#include "defines.hpp"

using namespace routing;
using namespace std;
using namespace track_analyzing;

namespace
{
MaxspeedType constexpr kMaxspeedTopBound = 200;
auto constexpr kValidTrafficValue = traffic::SpeedGroup::G5;

string TypeToString(uint32_t type)
{
  if (type == 0)
    return "unknown-type";

  return classif().GetReadableObjectName(type);
}

bool DayTimeToBool(DayTimeType type)
{
  switch (type)
  {
  case DayTimeType::Day:
  case DayTimeType::PolarDay:
    return true;
  case DayTimeType::Night:
  case DayTimeType::PolarNight:
    return false;
  }

  UNREACHABLE();
}

class CarModelTypes final
{
public:
  CarModelTypes()
  {
    for (auto const & additionalTag : CarModel::GetAdditionalTags())
      m_hwtags.push_back(classif().GetTypeByPath(additionalTag.m_hwtag));

    for (auto const & speedForType : CarModel::GetOptions())
      m_hwtags.push_back(classif().GetTypeByPath(speedForType.m_types));

    for (auto const & surface : CarModel::GetSurfaces())
      m_surfaceTags.push_back(classif().GetTypeByPath(surface.m_types));
  }

  struct Type
  {
    bool operator<(Type const & rhs) const
    {
      return tie(m_hwType, m_surfaceType) < tie(rhs.m_hwType, rhs.m_surfaceType);
    }

    bool operator==(Type const & rhs) const
    {
      return tie(m_hwType, m_surfaceType) == tie(rhs.m_hwType, m_surfaceType);
    }

    bool operator!=(Type const & rhs) const
    {
      return !(*this == rhs);
    }

    string GetSummary() const
    {
      ostringstream out;
      out << TypeToString(m_hwType) << "," << TypeToString(m_surfaceType);
      return out.str();
    }

    uint32_t m_hwType = 0;
    uint32_t m_surfaceType = 0;
  };

  Type GetType(FeatureType & feature) const
  {
    Type ret;
    feature::TypesHolder holder(feature);
    for (uint32_t type : m_hwtags)
    {
      if (holder.Has(type))
      {
        ret.m_hwType = type;
        break;
      }
    }

    for (uint32_t type : m_surfaceTags)
    {
      if (holder.Has(type))
      {
        ret.m_surfaceType = type;
        break;
      }
    }

    return ret;
  }

private:
  vector<uint32_t> m_hwtags;
  vector<uint32_t> m_surfaceTags;
};

struct RoadInfo
{
  bool operator==(RoadInfo const & rhs) const
  {
    return tie(m_type, m_maxspeedKMpH, m_isCityRoad, m_isOneWay) ==
           tie(rhs.m_type, rhs.m_maxspeedKMpH, rhs.m_isCityRoad, rhs.m_isOneWay);
  }

  bool operator!=(RoadInfo const & rhs) const
  {
    return !(*this == rhs);
  }

  bool operator<(RoadInfo const & rhs) const
  {
    return tie(m_type, m_maxspeedKMpH, m_isCityRoad, m_isOneWay) <
           tie(rhs.m_type, rhs.m_maxspeedKMpH, rhs.m_isCityRoad, rhs.m_isOneWay);
  }

  string GetSummary() const
  {
    ostringstream out;
    out << TypeToString(m_type.m_hwType) << ","
        << TypeToString(m_type.m_surfaceType) << ","
        << m_maxspeedKMpH << ","
        << m_isCityRoad << ","
        << m_isOneWay;

    return out.str();
  }

  CarModelTypes::Type m_type;
  MaxspeedType m_maxspeedKMpH = kInvalidSpeed;
  bool m_isCityRoad = false;
  bool m_isOneWay = false;
};

class MoveType final
{
public:
  MoveType() = default;

  MoveType(RoadInfo const & roadType, traffic::SpeedGroup speedGroup, DataPoint const & dataPoint)
    : m_roadInfo(roadType), m_speedGroup(speedGroup), m_latLon(dataPoint.m_latLon)
  {
    m_isDayTime = DayTimeToBool(GetDayTime(dataPoint.m_timestamp, m_latLon.m_lat, m_latLon.m_lon));
  }

  bool operator==(MoveType const & rhs) const
  {
    return tie(m_roadInfo, m_speedGroup) == tie(rhs.m_roadInfo, rhs.m_speedGroup);
  }

  bool operator<(MoveType const & rhs) const
  {
    auto const lhsGroup = base::Underlying(m_speedGroup);
    auto const rhsGroup = base::Underlying(rhs.m_speedGroup);
    return tie(m_roadInfo, lhsGroup) < tie(rhs.m_roadInfo, rhsGroup);
  }

  bool IsValid() const
  {
    // In order to collect cleaner data we don't use speed group lower than G5.
    return m_roadInfo.m_type.m_hwType != 0 &&
           m_roadInfo.m_type.m_surfaceType != 0 &&
           m_speedGroup == kValidTrafficValue;
  }

  string GetSummary() const
  {
    ostringstream out;
    out << m_roadInfo.GetSummary() << ","
        << m_isDayTime << ","
        << m_latLon.m_lat << " " << m_latLon.m_lon;

    return out.str();
  }

private:
  RoadInfo m_roadInfo;
  traffic::SpeedGroup m_speedGroup = traffic::SpeedGroup::Unknown;
  ms::LatLon m_latLon;
  bool m_isDayTime = false;
};

class SpeedInfo final
{
public:
  void Add(double distance, uint64_t time, IsCrossroadChecker::CrossroadInfo const & crossroads)
  {
    m_totalDistance += distance;
    m_totalTime += time;
    IsCrossroadChecker::MergeCrossroads(crossroads, m_crossroads);
  }

  string GetSummary() const
  {
    ostringstream out;
    out << m_totalDistance << ","
        << m_totalTime << ","
        << CalcSpeedKMpH(m_totalDistance, m_totalTime) << ",";

    for (size_t i = 1; i < m_crossroads.size(); ++i)
    {
      out << m_crossroads[i];
      if (i != m_crossroads.size() - 1)
        out << ",";
    }

    return out.str();
  }

private:
  double m_totalDistance = 0.0;
  uint64_t m_totalTime = 0;
  IsCrossroadChecker::CrossroadInfo m_crossroads{};
};

class MoveTypeAggregator final
{
public:
  void Add(MoveType && moveType, IsCrossroadChecker::CrossroadInfo const & crossroads, MatchedTrack::const_iterator begin,
           MatchedTrack::const_iterator end, Geometry & geometry)
  {
    if (begin + 1 >= end)
      return;

    uint64_t const time = (end - 1)->GetDataPoint().m_timestamp - begin->GetDataPoint().m_timestamp;
    double const length = CalcSubtrackLength(begin, end, geometry);
    m_moveInfos[moveType].Add(length, time, crossroads);
  }

  string GetSummary(string const & user, string const & mwm) const
  {
    ostringstream out;
    for (auto const & it : m_moveInfos)
    {
      if (!it.first.IsValid())
        continue;

      out << user << "," << mwm << "," << it.first.GetSummary() << "," << it.second.GetSummary() << '\n';
    }

    return out.str();
  }

private:
  map<MoveType, SpeedInfo> m_moveInfos;
};

class MatchedTrackPointToMoveType final
{
public:
  MatchedTrackPointToMoveType(FilesContainerR const & container, VehicleModelInterface & vehicleModel)
    : m_featuresVector(container), m_vehicleModel(vehicleModel)
  {
    if (container.IsExist(CITY_ROADS_FILE_TAG))
      LoadCityRoads(container.GetFileName(), container.GetReader(CITY_ROADS_FILE_TAG), m_cityRoads);

    if (container.IsExist(MAXSPEEDS_FILE_TAG))
      LoadMaxspeeds(container.GetReader(MAXSPEEDS_FILE_TAG), m_maxspeeds);
  }

  MoveType GetMoveType(MatchedTrackPoint const & point)
  {
    auto const & dataPoint = point.GetDataPoint();
    return MoveType(GetRoadInfo(point.GetSegment()),
                    static_cast<traffic::SpeedGroup>(dataPoint.m_traffic),
                    dataPoint);
  }

private:
  RoadInfo GetRoadInfo(Segment const & segment)
  {
    auto const featureId = segment.GetFeatureId();
    if (featureId == m_prevFeatureId)
      return m_prevRoadInfo;

    auto feature = m_featuresVector.GetVector().GetByIndex(featureId);
    CHECK(feature, ());

    auto const maxspeed = m_maxspeeds.GetMaxspeed(featureId);
    auto const maxspeedValueKMpH = maxspeed.IsValid() ?
                                   min(maxspeed.GetSpeedKmPH(segment.IsForward()), kMaxspeedTopBound) :
                                   kInvalidSpeed;

    m_prevFeatureId = featureId;
    m_prevRoadInfo = {m_carModelTypes.GetType(*feature), maxspeedValueKMpH,
                      m_cityRoads.IsCityRoad(featureId), m_vehicleModel.IsOneWay(*feature)};

    return m_prevRoadInfo;
  }

  FeaturesVectorTest m_featuresVector;
  VehicleModelInterface & m_vehicleModel;
  CarModelTypes const m_carModelTypes;
  CityRoads m_cityRoads;
  Maxspeeds m_maxspeeds;
  uint32_t m_prevFeatureId = numeric_limits<uint32_t>::max();
  RoadInfo m_prevRoadInfo;
};
}  // namespace

namespace track_analyzing
{
void CmdTagsTable(string const & filepath, string const & trackExtension, StringFilter mwmFilter,
                  StringFilter userFilter)
{
  cout << "user,mwm,hw type,surface type,maxspeed km/h,is city road,is one way,is day,lat lon,distance,time,"
          "mean speed km/h,turn from smaller to bigger,turn from bigger to smaller,from link,to link,"
          "intersection with big,intersection with small,intersection with link\n";

  storage::Storage storage;
  storage.RegisterAllLocalMaps(false /* enableDiffs */);
  FrozenDataSource dataSource;
  auto numMwmIds = CreateNumMwmIds(storage);

  auto processMwm = [&](string const & mwmName, UserToMatchedTracks const & userToMatchedTracks) {
    if (mwmFilter(mwmName))
      return;

    auto const countryName = storage.GetTopmostParentFor(mwmName);
    auto const carModelFactory = make_shared<CarModelFactory>(VehicleModelFactory::CountryParentNameGetterFn{});
    shared_ptr<VehicleModelInterface> vehicleModel =
        carModelFactory->GetVehicleModelForCountry(mwmName);
    string const mwmFile = GetCurrentVersionMwmFile(storage, mwmName);
    MatchedTrackPointToMoveType pointToMoveType(FilesContainerR(make_unique<FileReader>(mwmFile)), *vehicleModel);
    Geometry geometry(GeometryLoader::CreateFromFile(mwmFile, vehicleModel));
    auto const vehicleType = VehicleType::Car;
    auto const edgeEstimator = EdgeEstimator::Create(vehicleType, *vehicleModel, nullptr /* trafficStash */);
    auto indexGraphLoader = IndexGraphLoader::Create(vehicleType, false /* loadAltitudes */, numMwmIds,
                                                     carModelFactory, edgeEstimator, dataSource);

    platform::CountryFile const countryFile(mwmName);
    auto localCountryFile = storage.GetLatestLocalFile(countryFile);
    CHECK(localCountryFile, ("Can't find latest country file for", countryFile.GetName()));
    if (!dataSource.IsLoaded(countryFile))
    {
      auto registerResult = dataSource.Register(*localCountryFile);
      CHECK_EQUAL(registerResult.second, MwmSet::RegResult::Success,
                  ("Can't register mwm", countryFile.GetName()));
    }

    auto const mwmId = numMwmIds->GetId(countryFile);
    IsCrossroadChecker checker(indexGraphLoader->GetIndexGraph(mwmId), geometry);

    for (auto const & kv : userToMatchedTracks)
    {
      string const & user = kv.first;
      if (userFilter(user))
        continue;

      for (auto const & track : kv.second)
      {
        if (track.size() <= 1)
          continue;

        MoveTypeAggregator aggregator;
        IsCrossroadChecker::CrossroadInfo info{};
        for (auto subtrackBegin = track.begin(); subtrackBegin != track.end();)
        {
          auto moveType = pointToMoveType.GetMoveType(*subtrackBegin);
          auto prev = subtrackBegin;
          auto end = subtrackBegin + 1;
          while (end != track.end() && pointToMoveType.GetMoveType(*end) == moveType)
          {
            IsCrossroadChecker::MergeCrossroads(checker(prev->GetSegment(), end->GetSegment()), info);
            prev = end;
            ++end;
          }

          // If it's not the end of the track than it could be a crossroad.
          IsCrossroadChecker::CrossroadInfo crossroad{};
          if (end != track.end())
          {
            crossroad = checker(prev->GetSegment(), end->GetSegment());
            IsCrossroadChecker::MergeCrossroads(crossroad, info);
          }

          aggregator.Add(move(moveType), info, subtrackBegin, end, geometry);
          subtrackBegin = end;
          info = move(crossroad);
        }

        auto const summary = aggregator.GetSummary(user, countryName);
        if (!summary.empty())
          cout << summary;
      }
    }
  };

  auto processTrack = [&](string const & filename, MwmToMatchedTracks const & mwmToMatchedTracks) {
    LOG(LINFO, ("Processing", filename));
    ForTracksSortedByMwmName(mwmToMatchedTracks, *numMwmIds, processMwm);
  };

  ForEachTrackFile(filepath, trackExtension, numMwmIds, processTrack);
}
}  // namespace track_analyzing
<commit_msg>[routing] Handling rare cases when two point of track has the same time.<commit_after>#include "track_analyzing/track_analyzer/crossroad_checker.hpp"

#include "track_analyzing/track.hpp"
#include "track_analyzing/utils.hpp"

#include "routing/city_roads.hpp"
#include "routing/geometry.hpp"
#include "routing/index_graph.hpp"
#include "routing/index_graph_loader.hpp"
#include "routing/maxspeeds.hpp"

#include "routing_common/car_model.hpp"
#include "routing_common/maxspeed_conversion.hpp"
#include "routing_common/vehicle_model.hpp"

#include "traffic/speed_groups.hpp"

#include "indexer/classificator.hpp"
#include "indexer/data_source.hpp"
#include "indexer/feature.hpp"
#include "indexer/feature_data.hpp"
#include "indexer/features_vector.hpp"

#include "storage/routing_helpers.hpp"
#include "storage/storage.hpp"

#include "coding/file_reader.hpp"

#include "geometry/latlon.hpp"

#include "base/assert.hpp"
#include "base/file_name_utils.hpp"
#include "base/logging.hpp"
#include "base/stl_helpers.hpp"
#include "base/sunrise_sunset.hpp"
#include "base/timer.hpp"

#include <algorithm>
#include <array>
#include <cstdint>
#include <iostream>
#include <limits>
#include <map>
#include <memory>
#include <sstream>
#include <string>
#include <tuple>
#include <utility>
#include <vector>

#include <boost/optional.hpp>

#include "defines.hpp"

using namespace routing;
using namespace std;
using namespace track_analyzing;

namespace
{
MaxspeedType constexpr kMaxspeedTopBound = 200;
auto constexpr kValidTrafficValue = traffic::SpeedGroup::G5;

string TypeToString(uint32_t type)
{
  if (type == 0)
    return "unknown-type";

  return classif().GetReadableObjectName(type);
}

bool DayTimeToBool(DayTimeType type)
{
  switch (type)
  {
  case DayTimeType::Day:
  case DayTimeType::PolarDay:
    return true;
  case DayTimeType::Night:
  case DayTimeType::PolarNight:
    return false;
  }

  UNREACHABLE();
}

class CarModelTypes final
{
public:
  CarModelTypes()
  {
    for (auto const & additionalTag : CarModel::GetAdditionalTags())
      m_hwtags.push_back(classif().GetTypeByPath(additionalTag.m_hwtag));

    for (auto const & speedForType : CarModel::GetOptions())
      m_hwtags.push_back(classif().GetTypeByPath(speedForType.m_types));

    for (auto const & surface : CarModel::GetSurfaces())
      m_surfaceTags.push_back(classif().GetTypeByPath(surface.m_types));
  }

  struct Type
  {
    bool operator<(Type const & rhs) const
    {
      return tie(m_hwType, m_surfaceType) < tie(rhs.m_hwType, rhs.m_surfaceType);
    }

    bool operator==(Type const & rhs) const
    {
      return tie(m_hwType, m_surfaceType) == tie(rhs.m_hwType, m_surfaceType);
    }

    bool operator!=(Type const & rhs) const
    {
      return !(*this == rhs);
    }

    string GetSummary() const
    {
      ostringstream out;
      out << TypeToString(m_hwType) << "," << TypeToString(m_surfaceType);
      return out.str();
    }

    uint32_t m_hwType = 0;
    uint32_t m_surfaceType = 0;
  };

  Type GetType(FeatureType & feature) const
  {
    Type ret;
    feature::TypesHolder holder(feature);
    for (uint32_t type : m_hwtags)
    {
      if (holder.Has(type))
      {
        ret.m_hwType = type;
        break;
      }
    }

    for (uint32_t type : m_surfaceTags)
    {
      if (holder.Has(type))
      {
        ret.m_surfaceType = type;
        break;
      }
    }

    return ret;
  }

private:
  vector<uint32_t> m_hwtags;
  vector<uint32_t> m_surfaceTags;
};

struct RoadInfo
{
  bool operator==(RoadInfo const & rhs) const
  {
    return tie(m_type, m_maxspeedKMpH, m_isCityRoad, m_isOneWay) ==
           tie(rhs.m_type, rhs.m_maxspeedKMpH, rhs.m_isCityRoad, rhs.m_isOneWay);
  }

  bool operator!=(RoadInfo const & rhs) const
  {
    return !(*this == rhs);
  }

  bool operator<(RoadInfo const & rhs) const
  {
    return tie(m_type, m_maxspeedKMpH, m_isCityRoad, m_isOneWay) <
           tie(rhs.m_type, rhs.m_maxspeedKMpH, rhs.m_isCityRoad, rhs.m_isOneWay);
  }

  string GetSummary() const
  {
    ostringstream out;
    out << TypeToString(m_type.m_hwType) << ","
        << TypeToString(m_type.m_surfaceType) << ","
        << m_maxspeedKMpH << ","
        << m_isCityRoad << ","
        << m_isOneWay;

    return out.str();
  }

  CarModelTypes::Type m_type;
  MaxspeedType m_maxspeedKMpH = kInvalidSpeed;
  bool m_isCityRoad = false;
  bool m_isOneWay = false;
};

class MoveType final
{
public:
  MoveType() = default;

  MoveType(RoadInfo const & roadType, traffic::SpeedGroup speedGroup, DataPoint const & dataPoint)
    : m_roadInfo(roadType), m_speedGroup(speedGroup), m_latLon(dataPoint.m_latLon)
  {
    m_isDayTime = DayTimeToBool(GetDayTime(dataPoint.m_timestamp, m_latLon.m_lat, m_latLon.m_lon));
  }

  bool operator==(MoveType const & rhs) const
  {
    return tie(m_roadInfo, m_speedGroup) == tie(rhs.m_roadInfo, rhs.m_speedGroup);
  }

  bool operator<(MoveType const & rhs) const
  {
    auto const lhsGroup = base::Underlying(m_speedGroup);
    auto const rhsGroup = base::Underlying(rhs.m_speedGroup);
    return tie(m_roadInfo, lhsGroup) < tie(rhs.m_roadInfo, rhsGroup);
  }

  bool IsValid() const
  {
    // In order to collect cleaner data we don't use speed group lower than G5.
    return m_roadInfo.m_type.m_hwType != 0 &&
           m_roadInfo.m_type.m_surfaceType != 0 &&
           m_speedGroup == kValidTrafficValue;
  }

  string GetSummary() const
  {
    ostringstream out;
    out << m_roadInfo.GetSummary() << ","
        << m_isDayTime << ","
        << m_latLon.m_lat << " " << m_latLon.m_lon;

    return out.str();
  }

private:
  RoadInfo m_roadInfo;
  traffic::SpeedGroup m_speedGroup = traffic::SpeedGroup::Unknown;
  ms::LatLon m_latLon;
  bool m_isDayTime = false;
};

class SpeedInfo final
{
public:
  void Add(double distance, uint64_t time, IsCrossroadChecker::CrossroadInfo const & crossroads)
  {
    m_totalDistance += distance;
    m_totalTime += time;
    IsCrossroadChecker::MergeCrossroads(crossroads, m_crossroads);
  }

  string GetSummary() const
  {
    ostringstream out;
    out << m_totalDistance << ","
        << m_totalTime << ","
        << CalcSpeedKMpH(m_totalDistance, m_totalTime) << ",";

    for (size_t i = 1; i < m_crossroads.size(); ++i)
    {
      out << m_crossroads[i];
      if (i != m_crossroads.size() - 1)
        out << ",";
    }

    return out.str();
  }

private:
  double m_totalDistance = 0.0;
  uint64_t m_totalTime = 0;
  IsCrossroadChecker::CrossroadInfo m_crossroads{};
};

class MoveTypeAggregator final
{
public:
  void Add(MoveType && moveType, IsCrossroadChecker::CrossroadInfo const & crossroads, MatchedTrack::const_iterator begin,
           MatchedTrack::const_iterator end, Geometry & geometry)
  {
    if (begin + 1 >= end)
      return;

    auto const & beginDataPoint = begin->GetDataPoint();
    auto const & endDataPoint = (end - 1)->GetDataPoint();
    uint64_t const time = endDataPoint.m_timestamp - beginDataPoint.m_timestamp;

    if (time == 0)
    {
      LOG(LWARNING, ("Track with the same time at the beginning and at the end. Beginning:",
                     beginDataPoint.m_latLon, " End:", endDataPoint.m_latLon,
                     " Timestamp:", beginDataPoint.m_timestamp, " Segment:", begin->GetSegment()));
      return;
    }

    double const length = CalcSubtrackLength(begin, end, geometry);
    m_moveInfos[moveType].Add(length, time, crossroads);
  }

  string GetSummary(string const & user, string const & mwm) const
  {
    ostringstream out;
    for (auto const & it : m_moveInfos)
    {
      if (!it.first.IsValid())
        continue;

      out << user << "," << mwm << "," << it.first.GetSummary() << "," << it.second.GetSummary() << '\n';
    }

    return out.str();
  }

private:
  map<MoveType, SpeedInfo> m_moveInfos;
};

class MatchedTrackPointToMoveType final
{
public:
  MatchedTrackPointToMoveType(FilesContainerR const & container, VehicleModelInterface & vehicleModel)
    : m_featuresVector(container), m_vehicleModel(vehicleModel)
  {
    if (container.IsExist(CITY_ROADS_FILE_TAG))
      LoadCityRoads(container.GetFileName(), container.GetReader(CITY_ROADS_FILE_TAG), m_cityRoads);

    if (container.IsExist(MAXSPEEDS_FILE_TAG))
      LoadMaxspeeds(container.GetReader(MAXSPEEDS_FILE_TAG), m_maxspeeds);
  }

  MoveType GetMoveType(MatchedTrackPoint const & point)
  {
    auto const & dataPoint = point.GetDataPoint();
    return MoveType(GetRoadInfo(point.GetSegment()),
                    static_cast<traffic::SpeedGroup>(dataPoint.m_traffic),
                    dataPoint);
  }

private:
  RoadInfo GetRoadInfo(Segment const & segment)
  {
    auto const featureId = segment.GetFeatureId();
    if (featureId == m_prevFeatureId)
      return m_prevRoadInfo;

    auto feature = m_featuresVector.GetVector().GetByIndex(featureId);
    CHECK(feature, ());

    auto const maxspeed = m_maxspeeds.GetMaxspeed(featureId);
    auto const maxspeedValueKMpH = maxspeed.IsValid() ?
                                   min(maxspeed.GetSpeedKmPH(segment.IsForward()), kMaxspeedTopBound) :
                                   kInvalidSpeed;

    m_prevFeatureId = featureId;
    m_prevRoadInfo = {m_carModelTypes.GetType(*feature), maxspeedValueKMpH,
                      m_cityRoads.IsCityRoad(featureId), m_vehicleModel.IsOneWay(*feature)};

    return m_prevRoadInfo;
  }

  FeaturesVectorTest m_featuresVector;
  VehicleModelInterface & m_vehicleModel;
  CarModelTypes const m_carModelTypes;
  CityRoads m_cityRoads;
  Maxspeeds m_maxspeeds;
  uint32_t m_prevFeatureId = numeric_limits<uint32_t>::max();
  RoadInfo m_prevRoadInfo;
};
}  // namespace

namespace track_analyzing
{
void CmdTagsTable(string const & filepath, string const & trackExtension, StringFilter mwmFilter,
                  StringFilter userFilter)
{
  cout << "user,mwm,hw type,surface type,maxspeed km/h,is city road,is one way,is day,lat lon,distance,time,"
          "mean speed km/h,turn from smaller to bigger,turn from bigger to smaller,from link,to link,"
          "intersection with big,intersection with small,intersection with link\n";

  storage::Storage storage;
  storage.RegisterAllLocalMaps(false /* enableDiffs */);
  FrozenDataSource dataSource;
  auto numMwmIds = CreateNumMwmIds(storage);

  auto processMwm = [&](string const & mwmName, UserToMatchedTracks const & userToMatchedTracks) {
    if (mwmFilter(mwmName))
      return;

    auto const countryName = storage.GetTopmostParentFor(mwmName);
    auto const carModelFactory = make_shared<CarModelFactory>(VehicleModelFactory::CountryParentNameGetterFn{});
    shared_ptr<VehicleModelInterface> vehicleModel =
        carModelFactory->GetVehicleModelForCountry(mwmName);
    string const mwmFile = GetCurrentVersionMwmFile(storage, mwmName);
    MatchedTrackPointToMoveType pointToMoveType(FilesContainerR(make_unique<FileReader>(mwmFile)), *vehicleModel);
    Geometry geometry(GeometryLoader::CreateFromFile(mwmFile, vehicleModel));
    auto const vehicleType = VehicleType::Car;
    auto const edgeEstimator = EdgeEstimator::Create(vehicleType, *vehicleModel, nullptr /* trafficStash */);
    auto indexGraphLoader = IndexGraphLoader::Create(vehicleType, false /* loadAltitudes */, numMwmIds,
                                                     carModelFactory, edgeEstimator, dataSource);

    platform::CountryFile const countryFile(mwmName);
    auto localCountryFile = storage.GetLatestLocalFile(countryFile);
    CHECK(localCountryFile, ("Can't find latest country file for", countryFile.GetName()));
    if (!dataSource.IsLoaded(countryFile))
    {
      auto registerResult = dataSource.Register(*localCountryFile);
      CHECK_EQUAL(registerResult.second, MwmSet::RegResult::Success,
                  ("Can't register mwm", countryFile.GetName()));
    }

    auto const mwmId = numMwmIds->GetId(countryFile);
    IsCrossroadChecker checker(indexGraphLoader->GetIndexGraph(mwmId), geometry);

    for (auto const & kv : userToMatchedTracks)
    {
      string const & user = kv.first;
      if (userFilter(user))
        continue;

      for (auto const & track : kv.second)
      {
        if (track.size() <= 1)
          continue;

        MoveTypeAggregator aggregator;
        IsCrossroadChecker::CrossroadInfo info{};
        for (auto subtrackBegin = track.begin(); subtrackBegin != track.end();)
        {
          auto moveType = pointToMoveType.GetMoveType(*subtrackBegin);
          auto prev = subtrackBegin;
          auto end = subtrackBegin + 1;
          while (end != track.end() && pointToMoveType.GetMoveType(*end) == moveType)
          {
            IsCrossroadChecker::MergeCrossroads(checker(prev->GetSegment(), end->GetSegment()), info);
            prev = end;
            ++end;
          }

          // If it's not the end of the track than it could be a crossroad.
          IsCrossroadChecker::CrossroadInfo crossroad{};
          if (end != track.end())
          {
            crossroad = checker(prev->GetSegment(), end->GetSegment());
            IsCrossroadChecker::MergeCrossroads(crossroad, info);
          }

          aggregator.Add(move(moveType), info, subtrackBegin, end, geometry);
          subtrackBegin = end;
          info = move(crossroad);
        }

        auto const summary = aggregator.GetSummary(user, countryName);
        if (!summary.empty())
          cout << summary;
      }
    }
  };

  auto processTrack = [&](string const & filename, MwmToMatchedTracks const & mwmToMatchedTracks) {
    LOG(LINFO, ("Processing", filename));
    ForTracksSortedByMwmName(mwmToMatchedTracks, *numMwmIds, processMwm);
  };

  ForEachTrackFile(filepath, trackExtension, numMwmIds, processTrack);
}
}  // namespace track_analyzing
<|endoftext|>


<commit_before>//===--- FileSystemStatCache.cpp - Caching for 'stat' calls ---------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
//  This file defines the FileSystemStatCache interface.
//
//===----------------------------------------------------------------------===//

#include "clang/Basic/FileSystemStatCache.h"
#include "llvm/System/Path.h"
using namespace clang;

MemorizeStatCalls::LookupResult
MemorizeStatCalls::getStat(const char *Path, struct stat &StatBuf) {
  LookupResult Result = statChained(Path, StatBuf);

  // Do not cache failed stats, it is easy to construct common inconsistent
  // situations if we do, and they are not important for PCH performance (which
  // currently only needs the stats to construct the initial FileManager
  // entries).
  if (Result == CacheMissing)
    return Result;

  // Cache file 'stat' results and directories with absolutely paths.
  if (!S_ISDIR(StatBuf.st_mode) || llvm::sys::Path(Path).isAbsolute())
    StatCalls[Path] = StatBuf;

  return Result;
}
<commit_msg>replicate a terrible hack to fix a build error on VC++<commit_after>//===--- FileSystemStatCache.cpp - Caching for 'stat' calls ---------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
//  This file defines the FileSystemStatCache interface.
//
//===----------------------------------------------------------------------===//

#include "clang/Basic/FileSystemStatCache.h"
#include "llvm/System/Path.h"
using namespace clang;

#if defined(_MSC_VER)
#define S_ISDIR(s) (_S_IFDIR & s)
#endif

MemorizeStatCalls::LookupResult
MemorizeStatCalls::getStat(const char *Path, struct stat &StatBuf) {
  LookupResult Result = statChained(Path, StatBuf);

  // Do not cache failed stats, it is easy to construct common inconsistent
  // situations if we do, and they are not important for PCH performance (which
  // currently only needs the stats to construct the initial FileManager
  // entries).
  if (Result == CacheMissing)
    return Result;

  // Cache file 'stat' results and directories with absolutely paths.
  if (!S_ISDIR(StatBuf.st_mode) || llvm::sys::Path(Path).isAbsolute())
    StatCalls[Path] = StatBuf;

  return Result;
}
<|endoftext|>


<commit_before>//===-- MachineInstrAnnot.cpp ---------------------------------------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file was developed by the LLVM research group and is distributed under
// the University of Illinois Open Source License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
//  This file defines Annotations used to pass information between code
//  generation phases.
//
//===----------------------------------------------------------------------===//

#include "../Target/SparcV9/MachineInstrAnnot.h"
#include "../Target/SparcV9/SparcV9TmpInstr.h"
#include "llvm/CodeGen/MachineCodeForInstruction.h"
#include "llvm/Instructions.h"
#include "llvm/Type.h"
using namespace llvm;

CallArgsDescriptor::CallArgsDescriptor(CallInst* _callInstr,
                                       TmpInstruction* _retAddrReg,
                                       bool _isVarArgs, bool _noPrototype)
  : callInstr(_callInstr),
    funcPtr(isa<Function>(_callInstr->getCalledValue())
            ? NULL : _callInstr->getCalledValue()),
    retAddrReg(_retAddrReg),
    isVarArgs(_isVarArgs),
    noPrototype(_noPrototype) {
  unsigned int numArgs = callInstr->getNumOperands();
  argInfoVec.reserve(numArgs);
  assert(callInstr->getOperand(0) == callInstr->getCalledValue()
         && "Operand 0 is ignored in the loop below!");
  for (unsigned int i=1; i < numArgs; ++i)
    argInfoVec.push_back(CallArgInfo(callInstr->getOperand(i)));

  // Enter this object in the MachineCodeForInstr object of the CallInst.
  // This transfers ownership of this object.
  MachineCodeForInstruction::get(callInstr).setCallArgsDescriptor(this);
}

CallInst *CallArgsDescriptor::getReturnValue() const {
  return (callInstr->getType() == Type::VoidTy? NULL : callInstr);
}

// Mechanism to get the descriptor for a CALL MachineInstr.
// We get the LLVM CallInstr from the ret. addr. register argument
// of the CALL MachineInstr (which is explicit operand #3 for indirect
// calls or the last implicit operand for direct calls).  We then get
// the CallArgsDescriptor from the MachineCodeForInstruction object for
// the CallInstr.
// This is roundabout but avoids adding a new map or annotation just
// to keep track of CallArgsDescriptors.
//
CallArgsDescriptor *CallArgsDescriptor::get(const MachineInstr* MI) {
  const TmpInstruction* retAddrReg =
    cast<TmpInstruction>(isa<Function>(MI->getOperand(0).getVRegValue())
                         ? MI->getImplicitRef(MI->getNumImplicitRefs()-1)
                         : MI->getOperand(2).getVRegValue());

  assert(retAddrReg->getNumOperands() == 1 &&
         isa<CallInst>(retAddrReg->getOperand(0)) &&
         "Location of callInstr arg for CALL instr. changed? FIX THIS CODE!");

  const CallInst* callInstr = cast<CallInst>(retAddrReg->getOperand(0));

  CallArgsDescriptor* desc =
    MachineCodeForInstruction::get(callInstr).getCallArgsDescriptor();
  assert(desc->getCallInst()==callInstr && "Incorrect call args descriptor?");
  return desc;
}
<commit_msg>Nuke this file<commit_after><|endoftext|>


<commit_before>#include "factory.h"
#include "except.h"
#ifdef USE_OPENCV
#include "opencv_video_source.h"
#include "opencv_video_target.h"
#endif // USE_OPENCV
#ifdef USE_EPIPHANSDK
#include "epiphansdk_video_source.h"
#endif
#ifdef USE_LIBVLC
#include "vlc_video_source.h"
#endif
#ifdef USE_FFMPEG
#include "ffmpeg_video_target.h"
#endif
#include <boost/python.hpp>
#include <boost/python/exception_translator.hpp>

using namespace boost::python;

class IVideoSourceWrapper : IVideoSource, wrapper<IVideoSource>
{
    bool get_frame_dimensions(int & width, int & height)
    {
        return this->get_override("get_frame_dimensions")(width, height);
    }

    bool get_frame(gg::VideoFrame & frame)
    {
        return this->get_override("get_frame")(frame);
    }

    double get_frame_rate()
    {
        return this->get_override("get_frame_rate")();
    }

    void set_sub_frame(int x, int y, int width, int height)
    {
        this->get_override("set_sub_frame")(x, y, width, height);
    }

    void get_full_frame()
    {
        this->get_override("get_full_frame")();
    }
};

class IVideoTargetWrapper : gg::IVideoTarget, wrapper<gg::IVideoTarget>
{
    void init(const std::string filepath, const float framerate)
    {
        this->get_override("init")(filepath, framerate);
    }

    void append(const gg::VideoFrame & frame)
    {
        this->get_override("append")(frame);
    }

    void finalise()
    {
        this->get_override("finalise")();
    }
};

void translate_VideoSourceError(gg::VideoSourceError const & e)
{
    std::string msg;
    msg.append("VideoSourceError: ").append(e.what());
    PyErr_SetString(PyExc_RuntimeError, msg.c_str());
}

void translate_DeviceNotFound(gg::DeviceNotFound const & e)
{
    std::string msg;
    msg.append("DeviceNotFound: ").append(e.what());
    PyErr_SetString(PyExc_IOError, msg.c_str());
}

void translate_DeviceOffline(gg::DeviceOffline const & e)
{
    std::string msg;
    msg.append("DeviceOffline: ").append(e.what());
    PyErr_SetString(PyExc_IOError, msg.c_str());
}

void translate_VideoTargetError(gg::VideoTargetError const & e)
{
    std::string msg;
    msg.append("VideoTargetError: ").append(e.what());
    PyErr_SetString(PyExc_RuntimeError, msg.c_str());
}

BOOST_PYTHON_MODULE(pygiftgrab)
{
    register_exception_translator<gg::VideoSourceError>(&translate_VideoSourceError);
    register_exception_translator<gg::DeviceNotFound>(&translate_DeviceNotFound);
    register_exception_translator<gg::DeviceOffline>(&translate_DeviceOffline);
    register_exception_translator<gg::VideoTargetError>(&translate_VideoTargetError);

    enum_<gg::ColourSpace>("ColourSpace")
        .value("BGRA", gg::ColourSpace::BGRA)
        .value("I420", gg::ColourSpace::I420)
    ;

    enum_<gg::Device>("Device")
        .value("DVI2PCIeDuo_SDI", gg::Device::DVI2PCIeDuo_SDI)
        .value("DVI2PCIeDuo_DVI", gg::Device::DVI2PCIeDuo_DVI)
    ;

    enum_<gg::Storage>("Storage")
        .value("File_HEVC", gg::Storage::File_HEVC)
        .value("File_XviD", gg::Storage::File_XviD)
        .value("File_VP9", gg::Storage::File_VP9)
    ;

    class_<gg::VideoFrame>("VideoFrame", init<enum gg::ColourSpace, bool>())
        .def(init<enum gg::ColourSpace, const size_t, const size_t>())
        .def("rows", &gg::VideoFrame::rows)
        .def("cols", &gg::VideoFrame::cols)
    ;

    class_<IVideoSource, boost::noncopyable>("IVideoSource", no_init)
    ;

#ifdef USE_OPENCV
    class_<VideoSourceOpenCV, bases<IVideoSource>, boost::noncopyable>(
                "VideoSourceOpenCV", init<int>())
        .def(init<char *>())
        .def("get_frame", &VideoSourceOpenCV::get_frame)
        .def("get_frame_dimensions", &VideoSourceOpenCV::get_frame_dimensions)
        .def("get_frame_rate", &VideoSourceOpenCV::get_frame_rate)
        .def("set_sub_frame", &VideoSourceOpenCV::set_sub_frame)
        .def("get_full_frame", &VideoSourceOpenCV::get_full_frame)
    ;
#endif // USE_OPENCV

#ifdef USE_EPIPHANSDK
    class_<gg::VideoSourceEpiphanSDK, bases<IVideoSource>, boost::noncopyable>(
                "VideoSourceEpiphanSDK", init<const std::string, const V2U_INT32>())
        .def("get_frame", &gg::VideoSourceEpiphanSDK::get_frame)
        .def("get_frame_dimensions", &gg::VideoSourceEpiphanSDK::get_frame_dimensions)
        .def("get_frame_rate", &gg::VideoSourceEpiphanSDK::get_frame_rate)
        .def("set_sub_frame", &gg::VideoSourceEpiphanSDK::set_sub_frame)
        .def("get_full_frame", &gg::VideoSourceEpiphanSDK::get_full_frame)
    ;
#endif

#ifdef USE_LIBVLC
    class_<gg::VideoSourceVLC, bases<IVideoSource>, boost::noncopyable>(
                "VideoSourceVLC", init<const std::string>())
        .def("get_frame", &gg::VideoSourceVLC::get_frame)
        .def("get_frame_dimensions", &gg::VideoSourceVLC::get_frame_dimensions)
        .def("get_frame_rate", &gg::VideoSourceVLC::get_frame_rate)
        .def("set_sub_frame", &gg::VideoSourceVLC::set_sub_frame)
        .def("get_full_frame", &gg::VideoSourceVLC::get_full_frame)
    ;
#endif

    class_<gg::IVideoTarget, boost::noncopyable>("IVideoTarget", no_init)
    ;

#ifdef USE_FFMPEG
    class_<gg::VideoTargetFFmpeg, bases<gg::IVideoTarget>, boost::noncopyable>(
                "VideoTargetFFmpeg", init<std::string>())
        .def("init", &gg::VideoTargetFFmpeg::init)
        .def("append", &gg::VideoTargetFFmpeg::append)
        .def("finalise", &gg::VideoTargetFFmpeg::finalise)
    ;
#endif

#ifdef USE_OPENCV
    class_<gg::VideoTargetOpenCV, bases<gg::IVideoTarget>, boost::noncopyable>(
                "VideoTargetOpenCV", init<std::string>())
        .def("init", &gg::VideoTargetOpenCV::init)
        .def("append", &gg::VideoTargetOpenCV::append)
        .def("finalise", &gg::VideoTargetOpenCV::finalise)
    ;
#endif // USE_OPENCV

    class_<gg::Factory>("Factory", no_init)
        .def("connect", &gg::Factory::connect,
             /* because client should never delete returned
              * object on its own, but should rather call
              * disconnect when done
              */
             return_value_policy<reference_existing_object>())
        .staticmethod("connect")
        .def("disconnect", &gg::Factory::disconnect)
        .staticmethod("disconnect")
        .def("writer", &gg::Factory::writer,
             // because ownership is passed to client
             return_value_policy<manage_new_object>())
        .staticmethod("writer")
    ;
}
<commit_msg>Issue #86: exported IObserver to Python<commit_after>#include "factory.h"
#include "except.h"
#ifdef USE_OPENCV
#include "opencv_video_source.h"
#include "opencv_video_target.h"
#endif // USE_OPENCV
#ifdef USE_EPIPHANSDK
#include "epiphansdk_video_source.h"
#endif
#ifdef USE_LIBVLC
#include "vlc_video_source.h"
#endif
#ifdef USE_FFMPEG
#include "ffmpeg_video_target.h"
#endif
#include <boost/python.hpp>
#include <boost/python/exception_translator.hpp>

using namespace boost::python;

class IVideoSourceWrapper : IVideoSource, wrapper<IVideoSource>
{
    bool get_frame_dimensions(int & width, int & height)
    {
        return this->get_override("get_frame_dimensions")(width, height);
    }

    bool get_frame(gg::VideoFrame & frame)
    {
        return this->get_override("get_frame")(frame);
    }

    double get_frame_rate()
    {
        return this->get_override("get_frame_rate")();
    }

    void set_sub_frame(int x, int y, int width, int height)
    {
        this->get_override("set_sub_frame")(x, y, width, height);
    }

    void get_full_frame()
    {
        this->get_override("get_full_frame")();
    }
};

class IVideoTargetWrapper : gg::IVideoTarget, wrapper<gg::IVideoTarget>
{
    void init(const std::string filepath, const float framerate)
    {
        this->get_override("init")(filepath, framerate);
    }

    void append(const gg::VideoFrame & frame)
    {
        this->get_override("append")(frame);
    }

    void finalise()
    {
        this->get_override("finalise")();
    }
};

void translate_VideoSourceError(gg::VideoSourceError const & e)
{
    std::string msg;
    msg.append("VideoSourceError: ").append(e.what());
    PyErr_SetString(PyExc_RuntimeError, msg.c_str());
}

void translate_DeviceNotFound(gg::DeviceNotFound const & e)
{
    std::string msg;
    msg.append("DeviceNotFound: ").append(e.what());
    PyErr_SetString(PyExc_IOError, msg.c_str());
}

void translate_DeviceOffline(gg::DeviceOffline const & e)
{
    std::string msg;
    msg.append("DeviceOffline: ").append(e.what());
    PyErr_SetString(PyExc_IOError, msg.c_str());
}

void translate_VideoTargetError(gg::VideoTargetError const & e)
{
    std::string msg;
    msg.append("VideoTargetError: ").append(e.what());
    PyErr_SetString(PyExc_RuntimeError, msg.c_str());
}

BOOST_PYTHON_MODULE(pygiftgrab)
{
    register_exception_translator<gg::VideoSourceError>(&translate_VideoSourceError);
    register_exception_translator<gg::DeviceNotFound>(&translate_DeviceNotFound);
    register_exception_translator<gg::DeviceOffline>(&translate_DeviceOffline);
    register_exception_translator<gg::VideoTargetError>(&translate_VideoTargetError);

    enum_<gg::ColourSpace>("ColourSpace")
        .value("BGRA", gg::ColourSpace::BGRA)
        .value("I420", gg::ColourSpace::I420)
    ;

    enum_<gg::Device>("Device")
        .value("DVI2PCIeDuo_SDI", gg::Device::DVI2PCIeDuo_SDI)
        .value("DVI2PCIeDuo_DVI", gg::Device::DVI2PCIeDuo_DVI)
    ;

    enum_<gg::Storage>("Storage")
        .value("File_HEVC", gg::Storage::File_HEVC)
        .value("File_XviD", gg::Storage::File_XviD)
        .value("File_VP9", gg::Storage::File_VP9)
    ;

    class_<gg::VideoFrame>("VideoFrame", init<enum gg::ColourSpace, bool>())
        .def(init<enum gg::ColourSpace, const size_t, const size_t>())
        .def("rows", &gg::VideoFrame::rows)
        .def("cols", &gg::VideoFrame::cols)
    ;

    class_<gg::IObserver>("IObserver", no_init)
    ;

    class_<IVideoSource, boost::noncopyable>("IVideoSource", no_init)
    ;

#ifdef USE_OPENCV
    class_<VideoSourceOpenCV, bases<IVideoSource>, boost::noncopyable>(
                "VideoSourceOpenCV", init<int>())
        .def(init<char *>())
        .def("get_frame", &VideoSourceOpenCV::get_frame)
        .def("get_frame_dimensions", &VideoSourceOpenCV::get_frame_dimensions)
        .def("get_frame_rate", &VideoSourceOpenCV::get_frame_rate)
        .def("set_sub_frame", &VideoSourceOpenCV::set_sub_frame)
        .def("get_full_frame", &VideoSourceOpenCV::get_full_frame)
    ;
#endif // USE_OPENCV

#ifdef USE_EPIPHANSDK
    class_<gg::VideoSourceEpiphanSDK, bases<IVideoSource>, boost::noncopyable>(
                "VideoSourceEpiphanSDK", init<const std::string, const V2U_INT32>())
        .def("get_frame", &gg::VideoSourceEpiphanSDK::get_frame)
        .def("get_frame_dimensions", &gg::VideoSourceEpiphanSDK::get_frame_dimensions)
        .def("get_frame_rate", &gg::VideoSourceEpiphanSDK::get_frame_rate)
        .def("set_sub_frame", &gg::VideoSourceEpiphanSDK::set_sub_frame)
        .def("get_full_frame", &gg::VideoSourceEpiphanSDK::get_full_frame)
    ;
#endif

#ifdef USE_LIBVLC
    class_<gg::VideoSourceVLC, bases<IVideoSource>, boost::noncopyable>(
                "VideoSourceVLC", init<const std::string>())
        .def("get_frame", &gg::VideoSourceVLC::get_frame)
        .def("get_frame_dimensions", &gg::VideoSourceVLC::get_frame_dimensions)
        .def("get_frame_rate", &gg::VideoSourceVLC::get_frame_rate)
        .def("set_sub_frame", &gg::VideoSourceVLC::set_sub_frame)
        .def("get_full_frame", &gg::VideoSourceVLC::get_full_frame)
    ;
#endif

    class_<gg::IVideoTarget, boost::noncopyable>("IVideoTarget", no_init)
    ;

#ifdef USE_FFMPEG
    class_<gg::VideoTargetFFmpeg, bases<gg::IVideoTarget>, boost::noncopyable>(
                "VideoTargetFFmpeg", init<std::string>())
        .def("init", &gg::VideoTargetFFmpeg::init)
        .def("append", &gg::VideoTargetFFmpeg::append)
        .def("finalise", &gg::VideoTargetFFmpeg::finalise)
    ;
#endif

#ifdef USE_OPENCV
    class_<gg::VideoTargetOpenCV, bases<gg::IVideoTarget>, boost::noncopyable>(
                "VideoTargetOpenCV", init<std::string>())
        .def("init", &gg::VideoTargetOpenCV::init)
        .def("append", &gg::VideoTargetOpenCV::append)
        .def("finalise", &gg::VideoTargetOpenCV::finalise)
    ;
#endif // USE_OPENCV

    class_<gg::Factory>("Factory", no_init)
        .def("connect", &gg::Factory::connect,
             /* because client should never delete returned
              * object on its own, but should rather call
              * disconnect when done
              */
             return_value_policy<reference_existing_object>())
        .staticmethod("connect")
        .def("disconnect", &gg::Factory::disconnect)
        .staticmethod("disconnect")
        .def("writer", &gg::Factory::writer,
             // because ownership is passed to client
             return_value_policy<manage_new_object>())
        .staticmethod("writer")
    ;
}
<|endoftext|>


<commit_before>//===-- PeepholeOptimizer.cpp - Peephole Optimizations --------------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// Perform peephole optimizations on the machine code:
//
// - Optimize Extensions
//
//     Optimization of sign / zero extension instructions. It may be extended to
//     handle other instructions with similar properties.
//
//     On some targets, some instructions, e.g. X86 sign / zero extension, may
//     leave the source value in the lower part of the result. This optimization
//     will replace some uses of the pre-extension value with uses of the
//     sub-register of the results.
//
// - Optimize Comparisons
//
//     Optimization of comparison instructions. For instance, in this code:
//
//       sub r1, 1
//       cmp r1, 0
//       bz  L1
//
//     If the "sub" instruction all ready sets (or could be modified to set) the
//     same flag that the "cmp" instruction sets and that "bz" uses, then we can
//     eliminate the "cmp" instruction.
//
//===----------------------------------------------------------------------===//

#define DEBUG_TYPE "peephole-opt"
#include "llvm/CodeGen/Passes.h"
#include "llvm/CodeGen/MachineDominators.h"
#include "llvm/CodeGen/MachineInstrBuilder.h"
#include "llvm/CodeGen/MachineRegisterInfo.h"
#include "llvm/Target/TargetInstrInfo.h"
#include "llvm/Target/TargetRegisterInfo.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/ADT/Statistic.h"
using namespace llvm;

// Optimize Extensions
static cl::opt<bool>
Aggressive("aggressive-ext-opt", cl::Hidden,
           cl::desc("Aggressive extension optimization"));

STATISTIC(NumReuse, "Number of extension results reused");

// Optimize Comparisons
static cl::opt<bool>
EnableOptCmps("enable-optimize-cmps", cl::init(true), cl::Hidden);

STATISTIC(NumEliminated, "Number of compares eliminated");

namespace {
  class PeepholeOptimizer : public MachineFunctionPass {
    const TargetMachine   *TM;
    const TargetInstrInfo *TII;
    MachineRegisterInfo   *MRI;
    MachineDominatorTree  *DT;  // Machine dominator tree

  public:
    static char ID; // Pass identification
    PeepholeOptimizer() : MachineFunctionPass(ID) {}

    virtual bool runOnMachineFunction(MachineFunction &MF);

    virtual void getAnalysisUsage(AnalysisUsage &AU) const {
      AU.setPreservesCFG();
      MachineFunctionPass::getAnalysisUsage(AU);
      if (Aggressive) {
        AU.addRequired<MachineDominatorTree>();
        AU.addPreserved<MachineDominatorTree>();
      }
    }

  private:
    bool OptimizeCmpInstr(MachineInstr *MI, MachineBasicBlock *MBB);
    bool OptimizeExtInstr(MachineInstr *MI, MachineBasicBlock *MBB,
                          SmallPtrSet<MachineInstr*, 8> &LocalMIs);
  };
}

char PeepholeOptimizer::ID = 0;
INITIALIZE_PASS(PeepholeOptimizer, "peephole-opts",
                "Peephole Optimizations", false, false);

FunctionPass *llvm::createPeepholeOptimizerPass() {
  return new PeepholeOptimizer();
}

/// OptimizeExtInstr - If instruction is a copy-like instruction, i.e. it reads
/// a single register and writes a single register and it does not modify the
/// source, and if the source value is preserved as a sub-register of the
/// result, then replace all reachable uses of the source with the subreg of the
/// result.
///
/// Do not generate an EXTRACT that is used only in a debug use, as this changes
/// the code. Since this code does not currently share EXTRACTs, just ignore all
/// debug uses.
bool PeepholeOptimizer::
OptimizeExtInstr(MachineInstr *MI, MachineBasicBlock *MBB,
                 SmallPtrSet<MachineInstr*, 8> &LocalMIs) {
  LocalMIs.insert(MI);

  unsigned SrcReg, DstReg, SubIdx;
  if (!TII->isCoalescableExtInstr(*MI, SrcReg, DstReg, SubIdx))
    return false;

  if (TargetRegisterInfo::isPhysicalRegister(DstReg) ||
      TargetRegisterInfo::isPhysicalRegister(SrcReg))
    return false;

  MachineRegisterInfo::use_nodbg_iterator UI = MRI->use_nodbg_begin(SrcReg);
  if (++UI == MRI->use_nodbg_end())
    // No other uses.
    return false;

  // The source has other uses. See if we can replace the other uses with use of
  // the result of the extension.
  SmallPtrSet<MachineBasicBlock*, 4> ReachedBBs;
  UI = MRI->use_nodbg_begin(DstReg);
  for (MachineRegisterInfo::use_nodbg_iterator UE = MRI->use_nodbg_end();
       UI != UE; ++UI)
    ReachedBBs.insert(UI->getParent());

  // Uses that are in the same BB of uses of the result of the instruction.
  SmallVector<MachineOperand*, 8> Uses;

  // Uses that the result of the instruction can reach.
  SmallVector<MachineOperand*, 8> ExtendedUses;

  bool ExtendLife = true;
  UI = MRI->use_nodbg_begin(SrcReg);
  for (MachineRegisterInfo::use_nodbg_iterator UE = MRI->use_nodbg_end();
       UI != UE; ++UI) {
    MachineOperand &UseMO = UI.getOperand();
    MachineInstr *UseMI = &*UI;
    if (UseMI == MI)
      continue;

    if (UseMI->isPHI()) {
      ExtendLife = false;
      continue;
    }

    // It's an error to translate this:
    //
    //    %reg1025 = <sext> %reg1024
    //     ...
    //    %reg1026 = SUBREG_TO_REG 0, %reg1024, 4
    //
    // into this:
    //
    //    %reg1025 = <sext> %reg1024
    //     ...
    //    %reg1027 = COPY %reg1025:4
    //    %reg1026 = SUBREG_TO_REG 0, %reg1027, 4
    //
    // The problem here is that SUBREG_TO_REG is there to assert that an
    // implicit zext occurs. It doesn't insert a zext instruction. If we allow
    // the COPY here, it will give us the value after the <sext>, not the
    // original value of %reg1024 before <sext>.
    if (UseMI->getOpcode() == TargetOpcode::SUBREG_TO_REG)
      continue;

    MachineBasicBlock *UseMBB = UseMI->getParent();
    if (UseMBB == MBB) {
      // Local uses that come after the extension.
      if (!LocalMIs.count(UseMI))
        Uses.push_back(&UseMO);
    } else if (ReachedBBs.count(UseMBB)) {
      // Non-local uses where the result of the extension is used. Always
      // replace these unless it's a PHI.
      Uses.push_back(&UseMO);
    } else if (Aggressive && DT->dominates(MBB, UseMBB)) {
      // We may want to extend the live range of the extension result in order
      // to replace these uses.
      ExtendedUses.push_back(&UseMO);
    } else {
      // Both will be live out of the def MBB anyway. Don't extend live range of
      // the extension result.
      ExtendLife = false;
      break;
    }
  }

  if (ExtendLife && !ExtendedUses.empty())
    // Extend the liveness of the extension result.
    std::copy(ExtendedUses.begin(), ExtendedUses.end(),
              std::back_inserter(Uses));

  // Now replace all uses.
  bool Changed = false;
  if (!Uses.empty()) {
    SmallPtrSet<MachineBasicBlock*, 4> PHIBBs;

    // Look for PHI uses of the extended result, we don't want to extend the
    // liveness of a PHI input. It breaks all kinds of assumptions down
    // stream. A PHI use is expected to be the kill of its source values.
    UI = MRI->use_nodbg_begin(DstReg);
    for (MachineRegisterInfo::use_nodbg_iterator
           UE = MRI->use_nodbg_end(); UI != UE; ++UI)
      if (UI->isPHI())
        PHIBBs.insert(UI->getParent());

    const TargetRegisterClass *RC = MRI->getRegClass(SrcReg);
    for (unsigned i = 0, e = Uses.size(); i != e; ++i) {
      MachineOperand *UseMO = Uses[i];
      MachineInstr *UseMI = UseMO->getParent();
      MachineBasicBlock *UseMBB = UseMI->getParent();
      if (PHIBBs.count(UseMBB))
        continue;

      unsigned NewVR = MRI->createVirtualRegister(RC);
      BuildMI(*UseMBB, UseMI, UseMI->getDebugLoc(),
              TII->get(TargetOpcode::COPY), NewVR)
        .addReg(DstReg, 0, SubIdx);

      UseMO->setReg(NewVR);
      ++NumReuse;
      Changed = true;
    }
  }

  return Changed;
}

/// OptimizeCmpInstr - If the instruction is a compare and the previous
/// instruction it's comparing against all ready sets (or could be modified to
/// set) the same flag as the compare, then we can remove the comparison and use
/// the flag from the previous instruction.
bool PeepholeOptimizer::OptimizeCmpInstr(MachineInstr *MI,
                                         MachineBasicBlock *MBB) {
  if (!EnableOptCmps) return false;

  // If this instruction is a comparison against zero and isn't comparing a
  // physical register, we can try to optimize it.
  unsigned SrcReg;
  int CmpValue;
  if (!TII->AnalyzeCompare(MI, SrcReg, CmpValue) ||
      TargetRegisterInfo::isPhysicalRegister(SrcReg) || CmpValue != 0)
    return false;

  MachineRegisterInfo::def_iterator DI = MRI->def_begin(SrcReg);
  if (llvm::next(DI) != MRI->def_end())
    // Only support one definition.
    return false;

  // Attempt to convert the defining instruction to set the "zero" flag.
  if (TII->ConvertToSetZeroFlag(&*DI, MI)) {
    ++NumEliminated;
    return true;
  }

  return false;
}

bool PeepholeOptimizer::runOnMachineFunction(MachineFunction &MF) {
  TM  = &MF.getTarget();
  TII = TM->getInstrInfo();
  MRI = &MF.getRegInfo();
  DT  = Aggressive ? &getAnalysis<MachineDominatorTree>() : 0;

  bool Changed = false;

  SmallPtrSet<MachineInstr*, 8> LocalMIs;
  for (MachineFunction::iterator I = MF.begin(), E = MF.end(); I != E; ++I) {
    MachineBasicBlock *MBB = &*I;
    LocalMIs.clear();

    for (MachineBasicBlock::iterator
           MII = I->begin(), ME = I->end(); MII != ME; ) {
      MachineInstr *MI = &*MII;

      if (MI->getDesc().isCompare()) {
        ++MII; // The iterator may become invalid if the compare is deleted.
        Changed |= OptimizeCmpInstr(MI, MBB);
      } else {
        Changed |= OptimizeExtInstr(MI, MBB, LocalMIs);
        ++MII;
      }
    }
  }

  return Changed;
}
<commit_msg>Revert r110718; it broke clang-i386-darwin9.<commit_after>//===-- PeepholeOptimizer.cpp - Peephole Optimizations --------------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// Perform peephole optimizations on the machine code:
//
// - Optimize Extensions
//
//     Optimization of sign / zero extension instructions. It may be extended to
//     handle other instructions with similar properties.
//
//     On some targets, some instructions, e.g. X86 sign / zero extension, may
//     leave the source value in the lower part of the result. This optimization
//     will replace some uses of the pre-extension value with uses of the
//     sub-register of the results.
//
// - Optimize Comparisons
//
//     Optimization of comparison instructions. For instance, in this code:
//
//       sub r1, 1
//       cmp r1, 0
//       bz  L1
//
//     If the "sub" instruction all ready sets (or could be modified to set) the
//     same flag that the "cmp" instruction sets and that "bz" uses, then we can
//     eliminate the "cmp" instruction.
//
//===----------------------------------------------------------------------===//

#define DEBUG_TYPE "peephole-opt"
#include "llvm/CodeGen/Passes.h"
#include "llvm/CodeGen/MachineDominators.h"
#include "llvm/CodeGen/MachineInstrBuilder.h"
#include "llvm/CodeGen/MachineRegisterInfo.h"
#include "llvm/Target/TargetInstrInfo.h"
#include "llvm/Target/TargetRegisterInfo.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/ADT/Statistic.h"
using namespace llvm;

// Optimize Extensions
static cl::opt<bool>
Aggressive("aggressive-ext-opt", cl::Hidden,
           cl::desc("Aggressive extension optimization"));

STATISTIC(NumReuse, "Number of extension results reused");

// Optimize Comparisons
static cl::opt<bool>
EnableOptCmps("enable-optimize-cmps", cl::init(false), cl::Hidden);

STATISTIC(NumEliminated, "Number of compares eliminated");

namespace {
  class PeepholeOptimizer : public MachineFunctionPass {
    const TargetMachine   *TM;
    const TargetInstrInfo *TII;
    MachineRegisterInfo   *MRI;
    MachineDominatorTree  *DT;  // Machine dominator tree

  public:
    static char ID; // Pass identification
    PeepholeOptimizer() : MachineFunctionPass(ID) {}

    virtual bool runOnMachineFunction(MachineFunction &MF);

    virtual void getAnalysisUsage(AnalysisUsage &AU) const {
      AU.setPreservesCFG();
      MachineFunctionPass::getAnalysisUsage(AU);
      if (Aggressive) {
        AU.addRequired<MachineDominatorTree>();
        AU.addPreserved<MachineDominatorTree>();
      }
    }

  private:
    bool OptimizeCmpInstr(MachineInstr *MI, MachineBasicBlock *MBB);
    bool OptimizeExtInstr(MachineInstr *MI, MachineBasicBlock *MBB,
                          SmallPtrSet<MachineInstr*, 8> &LocalMIs);
  };
}

char PeepholeOptimizer::ID = 0;
INITIALIZE_PASS(PeepholeOptimizer, "peephole-opts",
                "Peephole Optimizations", false, false);

FunctionPass *llvm::createPeepholeOptimizerPass() {
  return new PeepholeOptimizer();
}

/// OptimizeExtInstr - If instruction is a copy-like instruction, i.e. it reads
/// a single register and writes a single register and it does not modify the
/// source, and if the source value is preserved as a sub-register of the
/// result, then replace all reachable uses of the source with the subreg of the
/// result.
///
/// Do not generate an EXTRACT that is used only in a debug use, as this changes
/// the code. Since this code does not currently share EXTRACTs, just ignore all
/// debug uses.
bool PeepholeOptimizer::
OptimizeExtInstr(MachineInstr *MI, MachineBasicBlock *MBB,
                 SmallPtrSet<MachineInstr*, 8> &LocalMIs) {
  LocalMIs.insert(MI);

  unsigned SrcReg, DstReg, SubIdx;
  if (!TII->isCoalescableExtInstr(*MI, SrcReg, DstReg, SubIdx))
    return false;

  if (TargetRegisterInfo::isPhysicalRegister(DstReg) ||
      TargetRegisterInfo::isPhysicalRegister(SrcReg))
    return false;

  MachineRegisterInfo::use_nodbg_iterator UI = MRI->use_nodbg_begin(SrcReg);
  if (++UI == MRI->use_nodbg_end())
    // No other uses.
    return false;

  // The source has other uses. See if we can replace the other uses with use of
  // the result of the extension.
  SmallPtrSet<MachineBasicBlock*, 4> ReachedBBs;
  UI = MRI->use_nodbg_begin(DstReg);
  for (MachineRegisterInfo::use_nodbg_iterator UE = MRI->use_nodbg_end();
       UI != UE; ++UI)
    ReachedBBs.insert(UI->getParent());

  // Uses that are in the same BB of uses of the result of the instruction.
  SmallVector<MachineOperand*, 8> Uses;

  // Uses that the result of the instruction can reach.
  SmallVector<MachineOperand*, 8> ExtendedUses;

  bool ExtendLife = true;
  UI = MRI->use_nodbg_begin(SrcReg);
  for (MachineRegisterInfo::use_nodbg_iterator UE = MRI->use_nodbg_end();
       UI != UE; ++UI) {
    MachineOperand &UseMO = UI.getOperand();
    MachineInstr *UseMI = &*UI;
    if (UseMI == MI)
      continue;

    if (UseMI->isPHI()) {
      ExtendLife = false;
      continue;
    }

    // It's an error to translate this:
    //
    //    %reg1025 = <sext> %reg1024
    //     ...
    //    %reg1026 = SUBREG_TO_REG 0, %reg1024, 4
    //
    // into this:
    //
    //    %reg1025 = <sext> %reg1024
    //     ...
    //    %reg1027 = COPY %reg1025:4
    //    %reg1026 = SUBREG_TO_REG 0, %reg1027, 4
    //
    // The problem here is that SUBREG_TO_REG is there to assert that an
    // implicit zext occurs. It doesn't insert a zext instruction. If we allow
    // the COPY here, it will give us the value after the <sext>, not the
    // original value of %reg1024 before <sext>.
    if (UseMI->getOpcode() == TargetOpcode::SUBREG_TO_REG)
      continue;

    MachineBasicBlock *UseMBB = UseMI->getParent();
    if (UseMBB == MBB) {
      // Local uses that come after the extension.
      if (!LocalMIs.count(UseMI))
        Uses.push_back(&UseMO);
    } else if (ReachedBBs.count(UseMBB)) {
      // Non-local uses where the result of the extension is used. Always
      // replace these unless it's a PHI.
      Uses.push_back(&UseMO);
    } else if (Aggressive && DT->dominates(MBB, UseMBB)) {
      // We may want to extend the live range of the extension result in order
      // to replace these uses.
      ExtendedUses.push_back(&UseMO);
    } else {
      // Both will be live out of the def MBB anyway. Don't extend live range of
      // the extension result.
      ExtendLife = false;
      break;
    }
  }

  if (ExtendLife && !ExtendedUses.empty())
    // Extend the liveness of the extension result.
    std::copy(ExtendedUses.begin(), ExtendedUses.end(),
              std::back_inserter(Uses));

  // Now replace all uses.
  bool Changed = false;
  if (!Uses.empty()) {
    SmallPtrSet<MachineBasicBlock*, 4> PHIBBs;

    // Look for PHI uses of the extended result, we don't want to extend the
    // liveness of a PHI input. It breaks all kinds of assumptions down
    // stream. A PHI use is expected to be the kill of its source values.
    UI = MRI->use_nodbg_begin(DstReg);
    for (MachineRegisterInfo::use_nodbg_iterator
           UE = MRI->use_nodbg_end(); UI != UE; ++UI)
      if (UI->isPHI())
        PHIBBs.insert(UI->getParent());

    const TargetRegisterClass *RC = MRI->getRegClass(SrcReg);
    for (unsigned i = 0, e = Uses.size(); i != e; ++i) {
      MachineOperand *UseMO = Uses[i];
      MachineInstr *UseMI = UseMO->getParent();
      MachineBasicBlock *UseMBB = UseMI->getParent();
      if (PHIBBs.count(UseMBB))
        continue;

      unsigned NewVR = MRI->createVirtualRegister(RC);
      BuildMI(*UseMBB, UseMI, UseMI->getDebugLoc(),
              TII->get(TargetOpcode::COPY), NewVR)
        .addReg(DstReg, 0, SubIdx);

      UseMO->setReg(NewVR);
      ++NumReuse;
      Changed = true;
    }
  }

  return Changed;
}

/// OptimizeCmpInstr - If the instruction is a compare and the previous
/// instruction it's comparing against all ready sets (or could be modified to
/// set) the same flag as the compare, then we can remove the comparison and use
/// the flag from the previous instruction.
bool PeepholeOptimizer::OptimizeCmpInstr(MachineInstr *MI,
                                         MachineBasicBlock *MBB) {
  if (!EnableOptCmps) return false;

  // If this instruction is a comparison against zero and isn't comparing a
  // physical register, we can try to optimize it.
  unsigned SrcReg;
  int CmpValue;
  if (!TII->AnalyzeCompare(MI, SrcReg, CmpValue) ||
      TargetRegisterInfo::isPhysicalRegister(SrcReg) || CmpValue != 0)
    return false;

  MachineRegisterInfo::def_iterator DI = MRI->def_begin(SrcReg);
  if (llvm::next(DI) != MRI->def_end())
    // Only support one definition.
    return false;

  // Attempt to convert the defining instruction to set the "zero" flag.
  if (TII->ConvertToSetZeroFlag(&*DI, MI)) {
    ++NumEliminated;
    return true;
  }

  return false;
}

bool PeepholeOptimizer::runOnMachineFunction(MachineFunction &MF) {
  TM  = &MF.getTarget();
  TII = TM->getInstrInfo();
  MRI = &MF.getRegInfo();
  DT  = Aggressive ? &getAnalysis<MachineDominatorTree>() : 0;

  bool Changed = false;

  SmallPtrSet<MachineInstr*, 8> LocalMIs;
  for (MachineFunction::iterator I = MF.begin(), E = MF.end(); I != E; ++I) {
    MachineBasicBlock *MBB = &*I;
    LocalMIs.clear();

    for (MachineBasicBlock::iterator
           MII = I->begin(), ME = I->end(); MII != ME; ) {
      MachineInstr *MI = &*MII;

      if (MI->getDesc().isCompare()) {
        ++MII; // The iterator may become invalid if the compare is deleted.
        Changed |= OptimizeCmpInstr(MI, MBB);
      } else {
        Changed |= OptimizeExtInstr(MI, MBB, LocalMIs);
        ++MII;
      }
    }
  }

  return Changed;
}
<|endoftext|>