<commit_before>// Copyright 2018 The Crashpad Authors. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include "snapshot/fuchsia/memory_map_region_snapshot_fuchsia.h"

#include <dbghelp.h>
#include <zircon/syscalls.h>

#include "base/cxx17_backports.h"
#include "base/fuchsia/fuchsia_logging.h"
#include "base/logging.h"
#include "base/strings/stringprintf.h"
#include "gtest/gtest.h"
#include "snapshot/fuchsia/process_snapshot_fuchsia.h"
#include "test/multiprocess_exec.h"
#include "util/fuchsia/koid_utilities.h"
#include "util/fuchsia/scoped_task_suspend.h"

namespace crashpad {
namespace test {
namespace {

constexpr struct {
  uint32_t zircon_perm;
  size_t pages;
  uint32_t minidump_perm;
} kTestMappingPermAndSizes[] = {
    // Zircon doesn't currently allow write-only, execute-only, or
    // write-execute-only, returning ZX_ERR_INVALID_ARGS on map.
    {0, 5, PAGE_NOACCESS},
    {ZX_VM_PERM_READ, 6, PAGE_READONLY},
    // {ZX_VM_PERM_WRITE, 7, PAGE_WRITECOPY},
    // {ZX_VM_PERM_EXECUTE, 8, PAGE_EXECUTE},
    {ZX_VM_PERM_READ | ZX_VM_PERM_WRITE, 9, PAGE_READWRITE},
    {ZX_VM_PERM_READ | ZX_VM_PERM_EXECUTE, 10, PAGE_EXECUTE_READ},
    // {ZX_VM_PERM_WRITE | ZX_VM_PERM_EXECUTE, 11, PAGE_EXECUTE_WRITECOPY},
    {ZX_VM_PERM_READ | ZX_VM_PERM_WRITE | ZX_VM_PERM_EXECUTE,
     12,
     PAGE_EXECUTE_READWRITE},
};

CRASHPAD_CHILD_TEST_MAIN(AddressSpaceChildTestMain) {
  // Create specifically sized mappings/permissions and write the address in
  // our address space to the parent so that the reader can check they're read
  // correctly.
  for (const auto& t : kTestMappingPermAndSizes) {
    zx_handle_t vmo = ZX_HANDLE_INVALID;
    const size_t size = t.pages * PAGE_SIZE;
    zx_status_t status = zx_vmo_create(size, 0, &vmo);
    ZX_CHECK(status == ZX_OK, status) << "zx_vmo_create";
    status = zx_vmo_replace_as_executable(vmo, ZX_HANDLE_INVALID, &vmo);
    ZX_CHECK(status == ZX_OK, status) << "zx_vmo_replace_as_executable";
    uintptr_t mapping_addr = 0;
    status = zx_vmar_map(
        zx_vmar_root_self(), t.zircon_perm, 0, vmo, 0, size, &mapping_addr);
    ZX_CHECK(status == ZX_OK, status) << "zx_vmar_map";
    CheckedWriteFile(StdioFileHandle(StdioStream::kStandardOutput),
                     &mapping_addr,
                     sizeof(mapping_addr));
  }

  CheckedReadFileAtEOF(StdioFileHandle(StdioStream::kStandardInput));
  return 0;
}

bool HasSingleMatchingMapping(
    const std::vector<const MemoryMapRegionSnapshot*>& memory_map,
    uintptr_t address,
    size_t size,
    uint32_t perm) {
  const MemoryMapRegionSnapshot* matching = nullptr;
  for (const auto* region : memory_map) {
    const MINIDUMP_MEMORY_INFO& mmi = region->AsMinidumpMemoryInfo();
    if (mmi.BaseAddress == address) {
      if (matching) {
        LOG(ERROR) << "multiple mappings matching address";
        return false;
      }
      matching = region;
    }
  }

  if (!matching)
    return false;

  const MINIDUMP_MEMORY_INFO& matching_mmi = matching->AsMinidumpMemoryInfo();
  return matching_mmi.Protect == perm && matching_mmi.RegionSize == size;
}

class AddressSpaceTest : public MultiprocessExec {
 public:
  AddressSpaceTest() : MultiprocessExec() {
    SetChildTestMainFunction("AddressSpaceChildTestMain");
  }

  AddressSpaceTest(const AddressSpaceTest&) = delete;
  AddressSpaceTest& operator=(const AddressSpaceTest&) = delete;

  ~AddressSpaceTest() {}

 private:
  void MultiprocessParent() override {
    uintptr_t test_addresses[base::size(kTestMappingPermAndSizes)];
    for (size_t i = 0; i < base::size(test_addresses); ++i) {
      ASSERT_TRUE(ReadFileExactly(
          ReadPipeHandle(), &test_addresses[i], sizeof(test_addresses[i])));
    }

    ScopedTaskSuspend suspend(*ChildProcess());

    ProcessSnapshotFuchsia process_snapshot;
    ASSERT_TRUE(process_snapshot.Initialize(*ChildProcess()));

    for (size_t i = 0; i < base::size(test_addresses); ++i) {
      const auto& t = kTestMappingPermAndSizes[i];
      EXPECT_TRUE(HasSingleMatchingMapping(process_snapshot.MemoryMap(),
                                           test_addresses[i],
                                           t.pages * PAGE_SIZE,
                                           t.minidump_perm))
          << base::StringPrintf(
                 "index %zu, zircon_perm 0x%x, minidump_perm 0x%x",
                 i,
                 t.zircon_perm,
                 t.minidump_perm);
    }
  }
};

TEST(ProcessSnapshotFuchsiaTest, AddressSpaceMapping) {
  AddressSpaceTest test;
  test.Run();
}

CRASHPAD_CHILD_TEST_MAIN(StackPointerIntoInvalidLocation) {
  // Map a large block, output the base address of it, and block. The parent
  // will artificially set the SP into this large block to confirm that a huge
  // stack is not accidentally captured.
  zx_handle_t large_vmo;
  constexpr uint64_t kSize = 1 << 30u;
  zx_status_t status = zx_vmo_create(kSize, 0, &large_vmo);
  ZX_CHECK(status == ZX_OK, status) << "zx_vmo_create";
  zx_vaddr_t mapped_addr;
  status = zx_vmar_map(zx_vmar_root_self(),
                       ZX_VM_PERM_READ | ZX_VM_PERM_WRITE,
                       0,
                       large_vmo,
                       0,
                       kSize,
                       &mapped_addr);
  ZX_CHECK(status == ZX_OK, status) << "zx_vmar_map";
  CheckedWriteFile(StdioFileHandle(StdioStream::kStandardOutput),
                   &mapped_addr,
                   sizeof(mapped_addr));
  zx_nanosleep(ZX_TIME_INFINITE);
  return 0;
}

class InvalidStackPointerTest : public MultiprocessExec {
 public:
  InvalidStackPointerTest() : MultiprocessExec() {
    SetChildTestMainFunction("StackPointerIntoInvalidLocation");
    SetExpectedChildTermination(kTerminationNormal,
                                ZX_TASK_RETCODE_SYSCALL_KILL);
  }

  InvalidStackPointerTest(const InvalidStackPointerTest&) = delete;
  InvalidStackPointerTest& operator=(const InvalidStackPointerTest&) = delete;

  ~InvalidStackPointerTest() {}

 private:
  void MultiprocessParent() override {
    uint64_t address_of_large_mapping;
    ASSERT_TRUE(ReadFileExactly(ReadPipeHandle(),
                                &address_of_large_mapping,
                                sizeof(address_of_large_mapping)));

    ScopedTaskSuspend suspend(*ChildProcess());

    std::vector<zx::thread> threads = GetThreadHandles(*ChildProcess());
    ASSERT_EQ(threads.size(), 1u);

    zx_thread_state_general_regs_t regs;
    ASSERT_EQ(threads[0].read_state(
                  ZX_THREAD_STATE_GENERAL_REGS, &regs, sizeof(regs)),
              ZX_OK);

    constexpr uint64_t kOffsetIntoMapping = 1024;
#if defined(ARCH_CPU_X86_64)
    regs.rsp = address_of_large_mapping + kOffsetIntoMapping;
#elif defined(ARCH_CPU_ARM64)
    regs.sp = address_of_large_mapping + kOffsetIntoMapping;
#else
#error
#endif

    ASSERT_EQ(threads[0].write_state(
                  ZX_THREAD_STATE_GENERAL_REGS, &regs, sizeof(regs)),
              ZX_OK);

    ProcessSnapshotFuchsia process_snapshot;
    ASSERT_TRUE(process_snapshot.Initialize(*ChildProcess()));

    ASSERT_EQ(process_snapshot.Threads().size(), 1u);
    const MemorySnapshot* stack = process_snapshot.Threads()[0]->Stack();
    ASSERT_TRUE(stack);
    // Ensure the stack capture isn't unreasonably large.
    EXPECT_LT(stack->Size(), 10 * 1048576u);

    // As we've corrupted the child, don't let it run again.
    ASSERT_EQ(ChildProcess()->kill(), ZX_OK);
  }
};

// This is a test for a specific failure detailed in
// https://bugs.fuchsia.dev/p/fuchsia/issues/detail?id=41212. A test of stack
// behavior that was intentionally overflowing the stack, and so when Crashpad
// received the exception the SP did not point into the actual stack. This
// caused Crashpad to erronously capture the "stack" from the next mapping in
// the address space (which could be very large, cause OOM, etc.).
TEST(ProcessSnapshotFuchsiaTest, InvalidStackPointer) {
  InvalidStackPointerTest test;
  test.Run();
}

}  // namespace
}  // namespace test
}  // namespace crashpad
<commit_msg>Fuchsia: Migrate to zx_system_get_page_size<commit_after>// Copyright 2018 The Crashpad Authors. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include "snapshot/fuchsia/memory_map_region_snapshot_fuchsia.h"

#include <dbghelp.h>
#include <zircon/syscalls.h>

#include "base/cxx17_backports.h"
#include "base/fuchsia/fuchsia_logging.h"
#include "base/logging.h"
#include "base/strings/stringprintf.h"
#include "gtest/gtest.h"
#include "snapshot/fuchsia/process_snapshot_fuchsia.h"
#include "test/multiprocess_exec.h"
#include "util/fuchsia/koid_utilities.h"
#include "util/fuchsia/scoped_task_suspend.h"

namespace crashpad {
namespace test {
namespace {

constexpr struct {
  uint32_t zircon_perm;
  size_t pages;
  uint32_t minidump_perm;
} kTestMappingPermAndSizes[] = {
    // Zircon doesn't currently allow write-only, execute-only, or
    // write-execute-only, returning ZX_ERR_INVALID_ARGS on map.
    {0, 5, PAGE_NOACCESS},
    {ZX_VM_PERM_READ, 6, PAGE_READONLY},
    // {ZX_VM_PERM_WRITE, 7, PAGE_WRITECOPY},
    // {ZX_VM_PERM_EXECUTE, 8, PAGE_EXECUTE},
    {ZX_VM_PERM_READ | ZX_VM_PERM_WRITE, 9, PAGE_READWRITE},
    {ZX_VM_PERM_READ | ZX_VM_PERM_EXECUTE, 10, PAGE_EXECUTE_READ},
    // {ZX_VM_PERM_WRITE | ZX_VM_PERM_EXECUTE, 11, PAGE_EXECUTE_WRITECOPY},
    {ZX_VM_PERM_READ | ZX_VM_PERM_WRITE | ZX_VM_PERM_EXECUTE,
     12,
     PAGE_EXECUTE_READWRITE},
};

CRASHPAD_CHILD_TEST_MAIN(AddressSpaceChildTestMain) {
  // Create specifically sized mappings/permissions and write the address in
  // our address space to the parent so that the reader can check they're read
  // correctly.
  for (const auto& t : kTestMappingPermAndSizes) {
    zx_handle_t vmo = ZX_HANDLE_INVALID;
    const size_t size = t.pages * zx_system_get_page_size();
    zx_status_t status = zx_vmo_create(size, 0, &vmo);
    ZX_CHECK(status == ZX_OK, status) << "zx_vmo_create";
    status = zx_vmo_replace_as_executable(vmo, ZX_HANDLE_INVALID, &vmo);
    ZX_CHECK(status == ZX_OK, status) << "zx_vmo_replace_as_executable";
    uintptr_t mapping_addr = 0;
    status = zx_vmar_map(
        zx_vmar_root_self(), t.zircon_perm, 0, vmo, 0, size, &mapping_addr);
    ZX_CHECK(status == ZX_OK, status) << "zx_vmar_map";
    CheckedWriteFile(StdioFileHandle(StdioStream::kStandardOutput),
                     &mapping_addr,
                     sizeof(mapping_addr));
  }

  CheckedReadFileAtEOF(StdioFileHandle(StdioStream::kStandardInput));
  return 0;
}

bool HasSingleMatchingMapping(
    const std::vector<const MemoryMapRegionSnapshot*>& memory_map,
    uintptr_t address,
    size_t size,
    uint32_t perm) {
  const MemoryMapRegionSnapshot* matching = nullptr;
  for (const auto* region : memory_map) {
    const MINIDUMP_MEMORY_INFO& mmi = region->AsMinidumpMemoryInfo();
    if (mmi.BaseAddress == address) {
      if (matching) {
        LOG(ERROR) << "multiple mappings matching address";
        return false;
      }
      matching = region;
    }
  }

  if (!matching)
    return false;

  const MINIDUMP_MEMORY_INFO& matching_mmi = matching->AsMinidumpMemoryInfo();
  return matching_mmi.Protect == perm && matching_mmi.RegionSize == size;
}

class AddressSpaceTest : public MultiprocessExec {
 public:
  AddressSpaceTest() : MultiprocessExec() {
    SetChildTestMainFunction("AddressSpaceChildTestMain");
  }

  AddressSpaceTest(const AddressSpaceTest&) = delete;
  AddressSpaceTest& operator=(const AddressSpaceTest&) = delete;

  ~AddressSpaceTest() {}

 private:
  void MultiprocessParent() override {
    uintptr_t test_addresses[base::size(kTestMappingPermAndSizes)];
    for (size_t i = 0; i < base::size(test_addresses); ++i) {
      ASSERT_TRUE(ReadFileExactly(
          ReadPipeHandle(), &test_addresses[i], sizeof(test_addresses[i])));
    }

    ScopedTaskSuspend suspend(*ChildProcess());

    ProcessSnapshotFuchsia process_snapshot;
    ASSERT_TRUE(process_snapshot.Initialize(*ChildProcess()));

    for (size_t i = 0; i < base::size(test_addresses); ++i) {
      const auto& t = kTestMappingPermAndSizes[i];
      EXPECT_TRUE(HasSingleMatchingMapping(process_snapshot.MemoryMap(),
                                           test_addresses[i],
                                           t.pages * zx_system_get_page_size(),
                                           t.minidump_perm))
          << base::StringPrintf(
                 "index %zu, zircon_perm 0x%x, minidump_perm 0x%x",
                 i,
                 t.zircon_perm,
                 t.minidump_perm);
    }
  }
};

TEST(ProcessSnapshotFuchsiaTest, AddressSpaceMapping) {
  AddressSpaceTest test;
  test.Run();
}

CRASHPAD_CHILD_TEST_MAIN(StackPointerIntoInvalidLocation) {
  // Map a large block, output the base address of it, and block. The parent
  // will artificially set the SP into this large block to confirm that a huge
  // stack is not accidentally captured.
  zx_handle_t large_vmo;
  constexpr uint64_t kSize = 1 << 30u;
  zx_status_t status = zx_vmo_create(kSize, 0, &large_vmo);
  ZX_CHECK(status == ZX_OK, status) << "zx_vmo_create";
  zx_vaddr_t mapped_addr;
  status = zx_vmar_map(zx_vmar_root_self(),
                       ZX_VM_PERM_READ | ZX_VM_PERM_WRITE,
                       0,
                       large_vmo,
                       0,
                       kSize,
                       &mapped_addr);
  ZX_CHECK(status == ZX_OK, status) << "zx_vmar_map";
  CheckedWriteFile(StdioFileHandle(StdioStream::kStandardOutput),
                   &mapped_addr,
                   sizeof(mapped_addr));
  zx_nanosleep(ZX_TIME_INFINITE);
  return 0;
}

class InvalidStackPointerTest : public MultiprocessExec {
 public:
  InvalidStackPointerTest() : MultiprocessExec() {
    SetChildTestMainFunction("StackPointerIntoInvalidLocation");
    SetExpectedChildTermination(kTerminationNormal,
                                ZX_TASK_RETCODE_SYSCALL_KILL);
  }

  InvalidStackPointerTest(const InvalidStackPointerTest&) = delete;
  InvalidStackPointerTest& operator=(const InvalidStackPointerTest&) = delete;

  ~InvalidStackPointerTest() {}

 private:
  void MultiprocessParent() override {
    uint64_t address_of_large_mapping;
    ASSERT_TRUE(ReadFileExactly(ReadPipeHandle(),
                                &address_of_large_mapping,
                                sizeof(address_of_large_mapping)));

    ScopedTaskSuspend suspend(*ChildProcess());

    std::vector<zx::thread> threads = GetThreadHandles(*ChildProcess());
    ASSERT_EQ(threads.size(), 1u);

    zx_thread_state_general_regs_t regs;
    ASSERT_EQ(threads[0].read_state(
                  ZX_THREAD_STATE_GENERAL_REGS, &regs, sizeof(regs)),
              ZX_OK);

    constexpr uint64_t kOffsetIntoMapping = 1024;
#if defined(ARCH_CPU_X86_64)
    regs.rsp = address_of_large_mapping + kOffsetIntoMapping;
#elif defined(ARCH_CPU_ARM64)
    regs.sp = address_of_large_mapping + kOffsetIntoMapping;
#else
#error
#endif

    ASSERT_EQ(threads[0].write_state(
                  ZX_THREAD_STATE_GENERAL_REGS, &regs, sizeof(regs)),
              ZX_OK);

    ProcessSnapshotFuchsia process_snapshot;
    ASSERT_TRUE(process_snapshot.Initialize(*ChildProcess()));

    ASSERT_EQ(process_snapshot.Threads().size(), 1u);
    const MemorySnapshot* stack = process_snapshot.Threads()[0]->Stack();
    ASSERT_TRUE(stack);
    // Ensure the stack capture isn't unreasonably large.
    EXPECT_LT(stack->Size(), 10 * 1048576u);

    // As we've corrupted the child, don't let it run again.
    ASSERT_EQ(ChildProcess()->kill(), ZX_OK);
  }
};

// This is a test for a specific failure detailed in
// https://bugs.fuchsia.dev/p/fuchsia/issues/detail?id=41212. A test of stack
// behavior that was intentionally overflowing the stack, and so when Crashpad
// received the exception the SP did not point into the actual stack. This
// caused Crashpad to erronously capture the "stack" from the next mapping in
// the address space (which could be very large, cause OOM, etc.).
TEST(ProcessSnapshotFuchsiaTest, InvalidStackPointer) {
  InvalidStackPointerTest test;
  test.Run();
}

}  // namespace
}  // namespace test
}  // namespace crashpad
<|endoftext|>


<commit_before>/**
 * @copyright
 * ====================================================================
 * Copyright (c) 2007 CollabNet.  All rights reserved.
 *
 * This software is licensed as described in the file COPYING, which
 * you should have received as part of this distribution.  The terms
 * are also available at http://subversion.tigris.org/license-1.html.
 * If newer versions of this license are posted there, you may use a
 * newer version instead, at your option.
 *
 * This software consists of voluntary contributions made by many
 * individuals.  For exact contribution history, see the revision
 * history and logs, available at http://subversion.tigris.org/.
 * ====================================================================
 * @endcopyright
 *
 * @file InfoCallback.cpp
 * @brief Implementation of the class InfoCallback
 */

#include "SVNClient.h"
#include "InfoCallback.h"
#include "EnumMapper.h"
#include "JNIUtil.h"
#include "svn_time.h"
#include "svn_path.h"

struct info_entry
{
    const char *path;
    bool copied;
    bool deleted;
    bool absent;
    bool incomplete;
    svn_info_t *info;
};

/**
 * Create a InfoCallback object.  jcallback is the java callback object.
 */
InfoCallback::InfoCallback(jobject jcallback)
{
    m_callback = jcallback;
    wcPath = NULL;
}

/**
 * Destroy a InfoCallback object
 */
InfoCallback::~InfoCallback()
{
    // the m_callback does not need to be destroyed, because it is the passed
    // in parameter to the java SVNClient.info method.
}

svn_error_t *
InfoCallback::callback(void *baton,
                       const char *path,
                       const svn_info_t *info,
                       apr_pool_t *pool)
{
    if (baton)
        return ((InfoCallback *)baton)->singleInfo(path, info, pool);

    return SVN_NO_ERROR;
}

void
InfoCallback::setWcPath(const char *path)
{
    wcPath = path;
}

/**
 * Callback called for a single path.  path is the path name, pool may be used
 * for memory allocation.
 */
svn_error_t *
InfoCallback::singleInfo(const char *path,
                         const svn_info_t *info,
                         apr_pool_t *pool)
{
    JNIEnv *env = JNIUtil::getEnv();

    static jmethodID mid = 0; // the method id will not change during
                              // the time this library is loaded, so
                              // it can be cached.
    if (mid == 0)
    {
        jclass clazz = env->FindClass(JAVA_PACKAGE"/InfoCallback");
        if (JNIUtil::isJavaExceptionThrown())
            return SVN_NO_ERROR;

        mid = env->GetMethodID(clazz, "singleInfo",
            "(L"JAVA_PACKAGE"/Info2;)V");
        if (JNIUtil::isJavaExceptionThrown() || mid == 0)
            return SVN_NO_ERROR;

        env->DeleteLocalRef(clazz);
        if (JNIUtil::isJavaExceptionThrown())
            return SVN_NO_ERROR;
    }

    info_entry infoEntry;
    SVN_JNI_ERR(createInfoEntry(infoEntry, path, info, pool), SVN_NO_ERROR);
    jobject jinfo2 = createJavaInfo2(&infoEntry);

    env->CallVoidMethod(m_callback, mid, jinfo2);
    if (JNIUtil::isJavaExceptionThrown())
        return SVN_NO_ERROR;

    env->DeleteLocalRef(jinfo2);
    // Return SVN_NO_ERROR here regardless of an exception or not.

    return SVN_NO_ERROR;
}

svn_error_t *
InfoCallback::createInfoEntry(info_entry &infoEntry, const char *path,
                              const svn_info_t *info, apr_pool_t *pool)
{
    svn_wc_adm_access_t *adm_access;
    const svn_wc_entry_t *entry;
    const char *full_path;

    // If we've cached the wcPath, it means that
    if (wcPath != NULL)
        full_path = svn_path_join(wcPath, path, pool);
    else
        full_path = path;

    SVN_ERR(svn_wc_adm_probe_open2(&adm_access, NULL, full_path, FALSE, 0,
                                   pool));
    SVN_ERR(svn_wc_entry(&entry, path, adm_access, FALSE, pool));
    SVN_ERR(svn_wc_adm_close(adm_access));

    if (!entry)
    {
        // We want to store a NULL in the resulting array, but we can't put a
        // NULL reference into the infoVect vector, so we just set the path to
        // NULL, and use that later.
        infoEntry.path = NULL;
        return SVN_NO_ERROR;
    }

    infoEntry.copied = entry->copied;
    infoEntry.deleted = entry->deleted;
    infoEntry.absent = entry->absent;
    infoEntry.incomplete = entry->incomplete;

    // we don't create here java Status object as we don't want too many local
    // references
    infoEntry.path = apr_pstrdup(pool,path);
    infoEntry.info = (svn_info_t*)apr_pcalloc(pool,
                                              sizeof(svn_info_t));
    infoEntry.info->URL = apr_pstrdup(pool,info->URL);
    infoEntry.info->rev = info->rev;
    infoEntry.info->kind = info->kind;
    infoEntry.info->repos_root_URL = apr_pstrdup(pool,
        info->repos_root_URL);
    infoEntry.info->repos_UUID = apr_pstrdup(pool, info->repos_UUID);
    infoEntry.info->last_changed_rev = info->last_changed_rev;
    infoEntry.info->last_changed_date = info->last_changed_date;
    infoEntry.info->last_changed_author = apr_pstrdup(pool,
        info->last_changed_author);
    if (info->lock != NULL)
        infoEntry.info->lock = svn_lock_dup(info->lock, pool);
    else
        infoEntry.info->lock = NULL;
    infoEntry.info->has_wc_info = info->has_wc_info;
    infoEntry.info->schedule = info->schedule;
    infoEntry.info->copyfrom_url = apr_pstrdup(pool,
        info->copyfrom_url);
    infoEntry.info->copyfrom_rev = info->copyfrom_rev;
    infoEntry.info->text_time = info->text_time;
    infoEntry.info->prop_time = info->prop_time;
    infoEntry.info->checksum = apr_pstrdup(pool, info->checksum);
    infoEntry.info->conflict_old = apr_pstrdup(pool,
        info->conflict_old);
    infoEntry.info->conflict_new = apr_pstrdup(pool,
        info->conflict_new);
    infoEntry.info->conflict_wrk = apr_pstrdup(pool,
        info->conflict_wrk);
    infoEntry.info->prejfile = apr_pstrdup(pool, info->prejfile);

    return SVN_NO_ERROR;
}

jobject
InfoCallback::createJavaInfo2(info_entry *infoEntry)
{
    const svn_info_t *info = infoEntry->info;
    JNIEnv *env = JNIUtil::getEnv();
    jclass clazz = env->FindClass(JAVA_PACKAGE"/Info2");
    if (JNIUtil::isJavaExceptionThrown())
        return NULL;

    static jmethodID mid = 0;
    if (mid == 0)
    {
        mid = env->GetMethodID(clazz, "<init>",
            "(Ljava/lang/String;Ljava/lang/String;JILjava/lang/String;"
             "Ljava/lang/String;JLjava/util/Date;Ljava/lang/String;"
             "Lorg/tigris/subversion/javahl/Lock;ZILjava/lang/String;J"
             "Ljava/util/Date;Ljava/util/Date;"
             "Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;"
             "Ljava/lang/String;Ljava/lang/String;ZZZZ)V");
        if (mid == 0 || JNIUtil::isJavaExceptionThrown())
            return NULL;
    }

    jstring jpath = JNIUtil::makeJString(infoEntry->path);
    if (JNIUtil::isJavaExceptionThrown())
        return NULL;

    jstring jurl = JNIUtil::makeJString(info->URL);
    if (JNIUtil::isJavaExceptionThrown())
        return NULL;

    jlong jrev = info->rev;
    jint jnodeKind = EnumMapper::mapNodeKind(info->kind);
    jstring jreposRootUrl = JNIUtil::makeJString(info->repos_root_URL);
    if (JNIUtil::isJavaExceptionThrown())
        return NULL;

    jstring jreportUUID = JNIUtil::makeJString(info->repos_UUID);
    if (JNIUtil::isJavaExceptionThrown())
        return NULL;

    jlong jlastChangedRev = info->last_changed_rev;
    jobject jlastChangedDate = JNIUtil::createDate(info->last_changed_date);
    if (JNIUtil::isJavaExceptionThrown())
        return NULL;

    jstring jlastChangedAuthor =
        JNIUtil::makeJString(info->last_changed_author);
    if (JNIUtil::isJavaExceptionThrown())
        return NULL;

    jobject jlock = SVNClient::createJavaLock(info->lock);
    if (JNIUtil::isJavaExceptionThrown())
        return NULL;

    jboolean jhasWcInfo = info->has_wc_info ? JNI_TRUE:JNI_FALSE;
    jint jschedule = EnumMapper::mapScheduleKind(info->schedule);
    jstring jcopyFromUrl = JNIUtil::makeJString(info->copyfrom_url);
    jlong jcopyFromRev = info->copyfrom_rev;
    jobject jtextTime = JNIUtil::createDate(info->text_time);
    if (JNIUtil::isJavaExceptionThrown())
        return NULL;

    jobject jpropTime = JNIUtil::createDate(info->prop_time);
    if (JNIUtil::isJavaExceptionThrown())
        return NULL;

    jstring jchecksum = JNIUtil::makeJString(info->checksum);
    if (JNIUtil::isJavaExceptionThrown())
        return NULL;

    jstring jconflictOld = JNIUtil::makeJString(info->conflict_old);
    if (JNIUtil::isJavaExceptionThrown())
        return NULL;

    jstring jconflictNew = JNIUtil::makeJString(info->conflict_new);
    if (JNIUtil::isJavaExceptionThrown())
        return NULL;

    jstring jconflictWrk = JNIUtil::makeJString(info->conflict_wrk);
    if (JNIUtil::isJavaExceptionThrown())
        return NULL;

    jstring jprejfile = JNIUtil::makeJString(info->prejfile);
    if (JNIUtil::isJavaExceptionThrown())
        return NULL;

    jboolean jcopied = infoEntry->copied ? JNI_TRUE : JNI_FALSE;
    jboolean jdeleted = infoEntry->deleted ? JNI_TRUE : JNI_FALSE;
    jboolean jabsent = infoEntry->absent ? JNI_TRUE : JNI_FALSE;
    jboolean jincomplete = infoEntry->incomplete ? JNI_TRUE : JNI_FALSE;

    jobject ret = env->NewObject(clazz, mid, jpath, jurl, jrev, jnodeKind,
        jreposRootUrl, jreportUUID, jlastChangedRev, jlastChangedDate,
        jlastChangedAuthor, jlock, jhasWcInfo, jschedule, jcopyFromUrl,
        jcopyFromRev, jtextTime, jpropTime, jchecksum, jconflictOld,
        jconflictNew, jconflictWrk, jprejfile, jcopied, jdeleted, jabsent,
        jincomplete);
    if (JNIUtil::isJavaExceptionThrown())
        return NULL;

    env->DeleteLocalRef(clazz);
    if (JNIUtil::isJavaExceptionThrown())
        return NULL;

    env->DeleteLocalRef(jpath);
    if (JNIUtil::isJavaExceptionThrown())
        return NULL;

    env->DeleteLocalRef(jurl);
    if (JNIUtil::isJavaExceptionThrown())
        return NULL;

    env->DeleteLocalRef(jreposRootUrl);
    if (JNIUtil::isJavaExceptionThrown())
        return NULL;

    env->DeleteLocalRef(jlastChangedDate);
    if (JNIUtil::isJavaExceptionThrown())
        return NULL;

    env->DeleteLocalRef(jlastChangedAuthor);
    if (JNIUtil::isJavaExceptionThrown())
        return NULL;

    env->DeleteLocalRef(jlock);
    if (JNIUtil::isJavaExceptionThrown())
        return NULL;

    env->DeleteLocalRef(jcopyFromUrl);
    if (JNIUtil::isJavaExceptionThrown())
        return NULL;

    env->DeleteLocalRef(jchecksum);
    if (JNIUtil::isJavaExceptionThrown())
        return NULL;

    env->DeleteLocalRef(jtextTime);
    if (JNIUtil::isJavaExceptionThrown())
        return NULL;

    env->DeleteLocalRef(jpropTime);
    if (JNIUtil::isJavaExceptionThrown())
        return NULL;

    env->DeleteLocalRef(jconflictOld);
    if (JNIUtil::isJavaExceptionThrown())
        return NULL;

    env->DeleteLocalRef(jconflictNew);
    if (JNIUtil::isJavaExceptionThrown())
        return NULL;

    env->DeleteLocalRef(jconflictWrk);
    if (JNIUtil::isJavaExceptionThrown())
        return NULL;

    env->DeleteLocalRef(jprejfile);
    if (JNIUtil::isJavaExceptionThrown())
        return NULL;

    return ret;
}
<commit_msg>JavaHL: Fix segfault when creating a Java Info2 object in the InfoCallback C++ code, using a temporary hack.  This segfault injected by r24349, and can be triggered by BasicTests.testBasicInfo2().<commit_after>/**
 * @copyright
 * ====================================================================
 * Copyright (c) 2007 CollabNet.  All rights reserved.
 *
 * This software is licensed as described in the file COPYING, which
 * you should have received as part of this distribution.  The terms
 * are also available at http://subversion.tigris.org/license-1.html.
 * If newer versions of this license are posted there, you may use a
 * newer version instead, at your option.
 *
 * This software consists of voluntary contributions made by many
 * individuals.  For exact contribution history, see the revision
 * history and logs, available at http://subversion.tigris.org/.
 * ====================================================================
 * @endcopyright
 *
 * @file InfoCallback.cpp
 * @brief Implementation of the class InfoCallback
 */

#include "SVNClient.h"
#include "InfoCallback.h"
#include "EnumMapper.h"
#include "JNIUtil.h"
#include "svn_time.h"
#include "svn_path.h"

struct info_entry
{
    const char *path;
    bool copied;
    bool deleted;
    bool absent;
    bool incomplete;
    svn_info_t *info;
};

/**
 * Create a InfoCallback object.  jcallback is the java callback object.
 */
InfoCallback::InfoCallback(jobject jcallback)
{
    m_callback = jcallback;
    wcPath = NULL;
}

/**
 * Destroy a InfoCallback object
 */
InfoCallback::~InfoCallback()
{
    // the m_callback does not need to be destroyed, because it is the passed
    // in parameter to the java SVNClient.info method.
}

svn_error_t *
InfoCallback::callback(void *baton,
                       const char *path,
                       const svn_info_t *info,
                       apr_pool_t *pool)
{
    if (baton)
        return ((InfoCallback *)baton)->singleInfo(path, info, pool);

    return SVN_NO_ERROR;
}

void
InfoCallback::setWcPath(const char *path)
{
    wcPath = path;
}

/**
 * Callback called for a single path.  path is the path name, pool may be used
 * for memory allocation.
 */
svn_error_t *
InfoCallback::singleInfo(const char *path,
                         const svn_info_t *info,
                         apr_pool_t *pool)
{
    JNIEnv *env = JNIUtil::getEnv();

    static jmethodID mid = 0; // the method id will not change during
                              // the time this library is loaded, so
                              // it can be cached.
    if (mid == 0)
    {
        jclass clazz = env->FindClass(JAVA_PACKAGE"/InfoCallback");
        if (JNIUtil::isJavaExceptionThrown())
            return SVN_NO_ERROR;

        mid = env->GetMethodID(clazz, "singleInfo",
            "(L"JAVA_PACKAGE"/Info2;)V");
        if (JNIUtil::isJavaExceptionThrown() || mid == 0)
            return SVN_NO_ERROR;

        env->DeleteLocalRef(clazz);
        if (JNIUtil::isJavaExceptionThrown())
            return SVN_NO_ERROR;
    }

    info_entry infoEntry;
    SVN_JNI_ERR(createInfoEntry(infoEntry, path, info, pool), SVN_NO_ERROR);
    jobject jinfo2 = createJavaInfo2(&infoEntry);

    env->CallVoidMethod(m_callback, mid, jinfo2);
    if (JNIUtil::isJavaExceptionThrown())
        return SVN_NO_ERROR;

    env->DeleteLocalRef(jinfo2);
    // Return SVN_NO_ERROR here regardless of an exception or not.

    return SVN_NO_ERROR;
}

svn_error_t *
InfoCallback::createInfoEntry(info_entry &infoEntry, const char *path,
                              const svn_info_t *info, apr_pool_t *pool)
{
    svn_wc_adm_access_t *adm_access;
    const svn_wc_entry_t *entry;
    const char *full_path;

    // If we've cached the wcPath, it means that
    if (wcPath != NULL)
        full_path = svn_path_join(wcPath, path, pool);
    else
        full_path = path;

    SVN_ERR(svn_wc_adm_probe_open2(&adm_access, NULL, full_path, FALSE, 0,
                                   pool));
    SVN_ERR(svn_wc_entry(&entry, path, adm_access, FALSE, pool));
    SVN_ERR(svn_wc_adm_close(adm_access));

    if (!entry)
    {
        // We want to store a NULL in the resulting array, but we can't put a
        // NULL reference into the infoVect vector, so we just set the path to
        // NULL, and use that later.
        infoEntry.path = NULL;
        return SVN_NO_ERROR;
    }

    infoEntry.copied = entry->copied;
    infoEntry.deleted = entry->deleted;
    infoEntry.absent = entry->absent;
    infoEntry.incomplete = entry->incomplete;

    // we don't create here java Status object as we don't want too many local
    // references
    infoEntry.path = apr_pstrdup(pool,path);
    infoEntry.info = (svn_info_t*)apr_pcalloc(pool,
                                              sizeof(svn_info_t));
    infoEntry.info->URL = apr_pstrdup(pool,info->URL);
    infoEntry.info->rev = info->rev;
    infoEntry.info->kind = info->kind;
    infoEntry.info->repos_root_URL = apr_pstrdup(pool,
        info->repos_root_URL);
    infoEntry.info->repos_UUID = apr_pstrdup(pool, info->repos_UUID);
    infoEntry.info->last_changed_rev = info->last_changed_rev;
    infoEntry.info->last_changed_date = info->last_changed_date;
    infoEntry.info->last_changed_author = apr_pstrdup(pool,
        info->last_changed_author);
    if (info->lock != NULL)
        infoEntry.info->lock = svn_lock_dup(info->lock, pool);
    else
        infoEntry.info->lock = NULL;
    infoEntry.info->has_wc_info = info->has_wc_info;
    infoEntry.info->schedule = info->schedule;
    infoEntry.info->copyfrom_url = apr_pstrdup(pool,
        info->copyfrom_url);
    infoEntry.info->copyfrom_rev = info->copyfrom_rev;
    infoEntry.info->text_time = info->text_time;
    infoEntry.info->prop_time = info->prop_time;
    infoEntry.info->checksum = apr_pstrdup(pool, info->checksum);
    infoEntry.info->conflict_old = apr_pstrdup(pool,
        info->conflict_old);
    infoEntry.info->conflict_new = apr_pstrdup(pool,
        info->conflict_new);
    infoEntry.info->conflict_wrk = apr_pstrdup(pool,
        info->conflict_wrk);
    infoEntry.info->prejfile = apr_pstrdup(pool, info->prejfile);

    return SVN_NO_ERROR;
}

jobject
InfoCallback::createJavaInfo2(info_entry *infoEntry)
{
    // ### HACK: We happen to know that a null path means that our
    // ### infoEntry is bogus.  We should fix or remove
    // ### createInfoEntry() instead of using this hack.
    if (infoEntry->path == NULL)
        return NULL;

    const svn_info_t *info = infoEntry->info;
    JNIEnv *env = JNIUtil::getEnv();
    jclass clazz = env->FindClass(JAVA_PACKAGE"/Info2");
    if (JNIUtil::isJavaExceptionThrown())
        return NULL;

    static jmethodID mid = 0;
    if (mid == 0)
    {
        mid = env->GetMethodID(clazz, "<init>",
            "(Ljava/lang/String;Ljava/lang/String;JILjava/lang/String;"
             "Ljava/lang/String;JLjava/util/Date;Ljava/lang/String;"
             "Lorg/tigris/subversion/javahl/Lock;ZILjava/lang/String;J"
             "Ljava/util/Date;Ljava/util/Date;"
             "Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;"
             "Ljava/lang/String;Ljava/lang/String;ZZZZ)V");
        if (mid == 0 || JNIUtil::isJavaExceptionThrown())
            return NULL;
    }

    jstring jpath = JNIUtil::makeJString(infoEntry->path);
    if (JNIUtil::isJavaExceptionThrown())
        return NULL;

    jstring jurl = JNIUtil::makeJString(info->URL);
    if (JNIUtil::isJavaExceptionThrown())
        return NULL;

    jlong jrev = info->rev;
    jint jnodeKind = EnumMapper::mapNodeKind(info->kind);
    jstring jreposRootUrl = JNIUtil::makeJString(info->repos_root_URL);
    if (JNIUtil::isJavaExceptionThrown())
        return NULL;

    jstring jreportUUID = JNIUtil::makeJString(info->repos_UUID);
    if (JNIUtil::isJavaExceptionThrown())
        return NULL;

    jlong jlastChangedRev = info->last_changed_rev;
    jobject jlastChangedDate = JNIUtil::createDate(info->last_changed_date);
    if (JNIUtil::isJavaExceptionThrown())
        return NULL;

    jstring jlastChangedAuthor =
        JNIUtil::makeJString(info->last_changed_author);
    if (JNIUtil::isJavaExceptionThrown())
        return NULL;

    jobject jlock = SVNClient::createJavaLock(info->lock);
    if (JNIUtil::isJavaExceptionThrown())
        return NULL;

    jboolean jhasWcInfo = info->has_wc_info ? JNI_TRUE:JNI_FALSE;
    jint jschedule = EnumMapper::mapScheduleKind(info->schedule);
    jstring jcopyFromUrl = JNIUtil::makeJString(info->copyfrom_url);
    jlong jcopyFromRev = info->copyfrom_rev;
    jobject jtextTime = JNIUtil::createDate(info->text_time);
    if (JNIUtil::isJavaExceptionThrown())
        return NULL;

    jobject jpropTime = JNIUtil::createDate(info->prop_time);
    if (JNIUtil::isJavaExceptionThrown())
        return NULL;

    jstring jchecksum = JNIUtil::makeJString(info->checksum);
    if (JNIUtil::isJavaExceptionThrown())
        return NULL;

    jstring jconflictOld = JNIUtil::makeJString(info->conflict_old);
    if (JNIUtil::isJavaExceptionThrown())
        return NULL;

    jstring jconflictNew = JNIUtil::makeJString(info->conflict_new);
    if (JNIUtil::isJavaExceptionThrown())
        return NULL;

    jstring jconflictWrk = JNIUtil::makeJString(info->conflict_wrk);
    if (JNIUtil::isJavaExceptionThrown())
        return NULL;

    jstring jprejfile = JNIUtil::makeJString(info->prejfile);
    if (JNIUtil::isJavaExceptionThrown())
        return NULL;

    jboolean jcopied = infoEntry->copied ? JNI_TRUE : JNI_FALSE;
    jboolean jdeleted = infoEntry->deleted ? JNI_TRUE : JNI_FALSE;
    jboolean jabsent = infoEntry->absent ? JNI_TRUE : JNI_FALSE;
    jboolean jincomplete = infoEntry->incomplete ? JNI_TRUE : JNI_FALSE;

    jobject ret = env->NewObject(clazz, mid, jpath, jurl, jrev, jnodeKind,
        jreposRootUrl, jreportUUID, jlastChangedRev, jlastChangedDate,
        jlastChangedAuthor, jlock, jhasWcInfo, jschedule, jcopyFromUrl,
        jcopyFromRev, jtextTime, jpropTime, jchecksum, jconflictOld,
        jconflictNew, jconflictWrk, jprejfile, jcopied, jdeleted, jabsent,
        jincomplete);
    if (JNIUtil::isJavaExceptionThrown())
        return NULL;

    env->DeleteLocalRef(clazz);
    if (JNIUtil::isJavaExceptionThrown())
        return NULL;

    env->DeleteLocalRef(jpath);
    if (JNIUtil::isJavaExceptionThrown())
        return NULL;

    env->DeleteLocalRef(jurl);
    if (JNIUtil::isJavaExceptionThrown())
        return NULL;

    env->DeleteLocalRef(jreposRootUrl);
    if (JNIUtil::isJavaExceptionThrown())
        return NULL;

    env->DeleteLocalRef(jlastChangedDate);
    if (JNIUtil::isJavaExceptionThrown())
        return NULL;

    env->DeleteLocalRef(jlastChangedAuthor);
    if (JNIUtil::isJavaExceptionThrown())
        return NULL;

    env->DeleteLocalRef(jlock);
    if (JNIUtil::isJavaExceptionThrown())
        return NULL;

    env->DeleteLocalRef(jcopyFromUrl);
    if (JNIUtil::isJavaExceptionThrown())
        return NULL;

    env->DeleteLocalRef(jchecksum);
    if (JNIUtil::isJavaExceptionThrown())
        return NULL;

    env->DeleteLocalRef(jtextTime);
    if (JNIUtil::isJavaExceptionThrown())
        return NULL;

    env->DeleteLocalRef(jpropTime);
    if (JNIUtil::isJavaExceptionThrown())
        return NULL;

    env->DeleteLocalRef(jconflictOld);
    if (JNIUtil::isJavaExceptionThrown())
        return NULL;

    env->DeleteLocalRef(jconflictNew);
    if (JNIUtil::isJavaExceptionThrown())
        return NULL;

    env->DeleteLocalRef(jconflictWrk);
    if (JNIUtil::isJavaExceptionThrown())
        return NULL;

    env->DeleteLocalRef(jprejfile);
    if (JNIUtil::isJavaExceptionThrown())
        return NULL;

    return ret;
}
<|endoftext|>


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

#ifndef _SVARRAY_HXX
#include <svtools/svarray.hxx>
#endif
#ifndef _COM_SUN_STAR_BEANS_PROPERTYVALUE_HXX_
#include <com/sun/star/beans/PropertyValue.hpp>
#endif
#ifndef _COM_SUN_STAR_BEANS_XPROPERTYSET_HXX_
#include <com/sun/star/beans/XPropertySet.hpp>
#endif
#ifndef _COM_SUN_STAR_BEANS_XPROPERTYSETINFO_HXX_
#include <com/sun/star/beans/XPropertySetInfo.hpp>
#endif
#ifndef _COM_SUN_STAR_BEANS_XPROPERTYACCESS_HXX_
#include <com/sun/star/beans/XPropertyAccess.hpp>
#endif
#ifndef _COM_SUN_STAR_BEANS_XPROPERTYCONTAINER_HXX_
#include <com/sun/star/beans/XPropertyContainer.hpp>
#endif

#ifndef _CPPUHELPER_IMPLBASE1_HXX_
#include <cppuhelper/implbase1.hxx>
#endif
#ifndef _CPPUHELPER_IMPLBASE2_HXX_
#include <cppuhelper/implbase2.hxx>
#endif

#define NS_BEANS    ::com::sun::star::beans
#define NS_LANG     ::com::sun::star::lang
#define NS_UNO      ::com::sun::star::uno

typedef NS_BEANS::PropertyValue* SbPropertyValuePtr;
SV_DECL_PTRARR( SbPropertyValueArr_Impl, SbPropertyValuePtr, 4, 4 );

typedef ::cppu::WeakImplHelper2< NS_BEANS::XPropertySet,
                                 NS_BEANS::XPropertyAccess > SbPropertyValuesHelper;

//==========================================================================

class SbPropertyValues:     public SbPropertyValuesHelper
{
    SbPropertyValueArr_Impl _aPropVals;
    NS_UNO::Reference< ::com::sun::star::beans::XPropertySetInfo > _xInfo;

private:
    INT32                   GetIndex_Impl( const ::rtl::OUString &rPropName ) const;

public:
                            SbPropertyValues();
    virtual                 ~SbPropertyValues();

    // XPropertySet
    virtual NS_UNO::Reference< NS_BEANS::XPropertySetInfo > SAL_CALL
        getPropertySetInfo(void) throw( NS_UNO::RuntimeException );
    virtual void SAL_CALL   setPropertyValue(
                                const ::rtl::OUString& aPropertyName,
                                const NS_UNO::Any& aValue)
                                throw (::com::sun::star::beans::UnknownPropertyException,
                                ::com::sun::star::beans::PropertyVetoException,
                                ::com::sun::star::lang::IllegalArgumentException,
                                ::com::sun::star::lang::WrappedTargetException,
                                ::com::sun::star::uno::RuntimeException);
    virtual NS_UNO::Any SAL_CALL getPropertyValue( const ::rtl::OUString& PropertyName )
        throw(  NS_BEANS::UnknownPropertyException,
                NS_LANG::WrappedTargetException,
                NS_UNO::RuntimeException);
    virtual void SAL_CALL   addPropertyChangeListener(
                                const ::rtl::OUString& aPropertyName,
                                const NS_UNO::Reference< NS_BEANS::XPropertyChangeListener >& )
                                throw ();
    virtual void SAL_CALL   removePropertyChangeListener(
                                const ::rtl::OUString& aPropertyName,
                                const NS_UNO::Reference< NS_BEANS::XPropertyChangeListener >& )
                                throw ();
    virtual void SAL_CALL   addVetoableChangeListener(
                                const ::rtl::OUString& aPropertyName,
                                const NS_UNO::Reference< NS_BEANS::XVetoableChangeListener >& )
                                throw ();
    virtual void SAL_CALL   removeVetoableChangeListener(
                                const ::rtl::OUString& aPropertyName,
                                const NS_UNO::Reference< NS_BEANS::XVetoableChangeListener >& )
                                throw ();

    // XPropertyAccess
    virtual NS_UNO::Sequence< NS_BEANS::PropertyValue > SAL_CALL getPropertyValues(void) throw (::com::sun::star::uno::RuntimeException);
    virtual void SAL_CALL setPropertyValues(const NS_UNO::Sequence< NS_BEANS::PropertyValue >& PropertyValues_) throw (::com::sun::star::beans::UnknownPropertyException, ::com::sun::star::beans::PropertyVetoException, ::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::lang::WrappedTargetException, ::com::sun::star::uno::RuntimeException);
};

//==========================================================================

typedef ::cppu::WeakImplHelper1< NS_BEANS::XPropertySetInfo > SbPropertySetInfoHelper;

// AB 20.3.2000 Help Class for XPropertySetInfo implementation
class PropertySetInfoImpl
{
    friend class SbPropertySetInfo;
    friend class SbPropertyContainer;

    NS_UNO::Sequence< NS_BEANS::Property > _aProps;

    sal_Int32 GetIndex_Impl( const ::rtl::OUString &rPropName ) const;

public:
    PropertySetInfoImpl();
    PropertySetInfoImpl( NS_UNO::Sequence< NS_BEANS::Property >& rProps );

    // XPropertySetInfo
    NS_UNO::Sequence< NS_BEANS::Property > SAL_CALL getProperties(void) throw ();
    NS_BEANS::Property SAL_CALL getPropertyByName(const ::rtl::OUString& Name)
        throw( NS_UNO::RuntimeException );
    sal_Bool SAL_CALL hasPropertyByName(const ::rtl::OUString& Name)
        throw ( NS_UNO::RuntimeException );
};

class SbPropertySetInfo:    public SbPropertySetInfoHelper
{
    PropertySetInfoImpl aImpl;

public:
                            SbPropertySetInfo();
                            SbPropertySetInfo( const SbPropertyValueArr_Impl &rPropVals );
    virtual                 ~SbPropertySetInfo();

    // XPropertySetInfo
    virtual NS_UNO::Sequence< NS_BEANS::Property > SAL_CALL getProperties(void)
        throw( NS_UNO::RuntimeException );
    virtual NS_BEANS::Property SAL_CALL getPropertyByName(const ::rtl::OUString& Name)
        throw( NS_UNO::RuntimeException );
    virtual sal_Bool SAL_CALL hasPropertyByName(const ::rtl::OUString& Name)
        throw( NS_UNO::RuntimeException );
};

//==========================================================================

typedef ::cppu::WeakImplHelper2< NS_BEANS::XPropertySetInfo, NS_BEANS::XPropertyContainer > SbPropertyContainerHelper;

class SbPropertyContainer: public SbPropertyContainerHelper
{
    PropertySetInfoImpl aImpl;

public:
                            SbPropertyContainer();
    virtual                 ~SbPropertyContainer();

    // XPropertyContainer
    virtual void SAL_CALL addProperty(  const ::rtl::OUString& Name,
                                        INT16 Attributes,
                                        const NS_UNO::Any& DefaultValue)
        throw(  NS_BEANS::PropertyExistException, NS_BEANS::IllegalTypeException,
                NS_LANG::IllegalArgumentException, NS_UNO::RuntimeException );
    virtual void SAL_CALL removeProperty(const ::rtl::OUString& Name)
        throw( NS_BEANS::UnknownPropertyException, NS_UNO::RuntimeException );

    // XPropertySetInfo
    virtual NS_UNO::Sequence< NS_BEANS::Property > SAL_CALL getProperties(void) throw();
    virtual NS_BEANS::Property SAL_CALL getPropertyByName(const ::rtl::OUString& Name)
        throw( NS_UNO::RuntimeException );
    virtual sal_Bool SAL_CALL hasPropertyByName(const ::rtl::OUString& Name)
        throw( NS_UNO::RuntimeException );

    // XPropertyAccess
    virtual NS_UNO::Sequence< NS_BEANS::PropertyValue > SAL_CALL getPropertyValues(void);
    virtual void SAL_CALL setPropertyValues(const NS_UNO::Sequence< NS_BEANS::PropertyValue >& PropertyValues_);
};

//=========================================================================

class StarBASIC;
class SbxArray;

void RTL_Impl_CreatePropertySet( StarBASIC* pBasic, SbxArray& rPar, BOOL bWrite );

#undef NS_BEANS
#undef NS_LANG
#undef NS_UNO

#endif

<commit_msg>INTEGRATION: CWS ooo19126 (1.2.352); FILE MERGED 2005/09/05 14:36:13 rt 1.2.352.1: #i54170# Change license header: remove SISSL<commit_after>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: propacc.hxx,v $
 *
 *  $Revision: 1.3 $
 *
 *  last change: $Author: rt $ $Date: 2005-09-07 21:34:53 $
 *
 *  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 _SFX_PROPBAG_HXX
#define _SFX_PROPBAG_HXX

#ifndef _SVARRAY_HXX
#include <svtools/svarray.hxx>
#endif
#ifndef _COM_SUN_STAR_BEANS_PROPERTYVALUE_HXX_
#include <com/sun/star/beans/PropertyValue.hpp>
#endif
#ifndef _COM_SUN_STAR_BEANS_XPROPERTYSET_HXX_
#include <com/sun/star/beans/XPropertySet.hpp>
#endif
#ifndef _COM_SUN_STAR_BEANS_XPROPERTYSETINFO_HXX_
#include <com/sun/star/beans/XPropertySetInfo.hpp>
#endif
#ifndef _COM_SUN_STAR_BEANS_XPROPERTYACCESS_HXX_
#include <com/sun/star/beans/XPropertyAccess.hpp>
#endif
#ifndef _COM_SUN_STAR_BEANS_XPROPERTYCONTAINER_HXX_
#include <com/sun/star/beans/XPropertyContainer.hpp>
#endif

#ifndef _CPPUHELPER_IMPLBASE1_HXX_
#include <cppuhelper/implbase1.hxx>
#endif
#ifndef _CPPUHELPER_IMPLBASE2_HXX_
#include <cppuhelper/implbase2.hxx>
#endif

#define NS_BEANS    ::com::sun::star::beans
#define NS_LANG     ::com::sun::star::lang
#define NS_UNO      ::com::sun::star::uno

typedef NS_BEANS::PropertyValue* SbPropertyValuePtr;
SV_DECL_PTRARR( SbPropertyValueArr_Impl, SbPropertyValuePtr, 4, 4 );

typedef ::cppu::WeakImplHelper2< NS_BEANS::XPropertySet,
                                 NS_BEANS::XPropertyAccess > SbPropertyValuesHelper;

//==========================================================================

class SbPropertyValues:     public SbPropertyValuesHelper
{
    SbPropertyValueArr_Impl _aPropVals;
    NS_UNO::Reference< ::com::sun::star::beans::XPropertySetInfo > _xInfo;

private:
    INT32                   GetIndex_Impl( const ::rtl::OUString &rPropName ) const;

public:
                            SbPropertyValues();
    virtual                 ~SbPropertyValues();

    // XPropertySet
    virtual NS_UNO::Reference< NS_BEANS::XPropertySetInfo > SAL_CALL
        getPropertySetInfo(void) throw( NS_UNO::RuntimeException );
    virtual void SAL_CALL   setPropertyValue(
                                const ::rtl::OUString& aPropertyName,
                                const NS_UNO::Any& aValue)
                                throw (::com::sun::star::beans::UnknownPropertyException,
                                ::com::sun::star::beans::PropertyVetoException,
                                ::com::sun::star::lang::IllegalArgumentException,
                                ::com::sun::star::lang::WrappedTargetException,
                                ::com::sun::star::uno::RuntimeException);
    virtual NS_UNO::Any SAL_CALL getPropertyValue( const ::rtl::OUString& PropertyName )
        throw(  NS_BEANS::UnknownPropertyException,
                NS_LANG::WrappedTargetException,
                NS_UNO::RuntimeException);
    virtual void SAL_CALL   addPropertyChangeListener(
                                const ::rtl::OUString& aPropertyName,
                                const NS_UNO::Reference< NS_BEANS::XPropertyChangeListener >& )
                                throw ();
    virtual void SAL_CALL   removePropertyChangeListener(
                                const ::rtl::OUString& aPropertyName,
                                const NS_UNO::Reference< NS_BEANS::XPropertyChangeListener >& )
                                throw ();
    virtual void SAL_CALL   addVetoableChangeListener(
                                const ::rtl::OUString& aPropertyName,
                                const NS_UNO::Reference< NS_BEANS::XVetoableChangeListener >& )
                                throw ();
    virtual void SAL_CALL   removeVetoableChangeListener(
                                const ::rtl::OUString& aPropertyName,
                                const NS_UNO::Reference< NS_BEANS::XVetoableChangeListener >& )
                                throw ();

    // XPropertyAccess
    virtual NS_UNO::Sequence< NS_BEANS::PropertyValue > SAL_CALL getPropertyValues(void) throw (::com::sun::star::uno::RuntimeException);
    virtual void SAL_CALL setPropertyValues(const NS_UNO::Sequence< NS_BEANS::PropertyValue >& PropertyValues_) throw (::com::sun::star::beans::UnknownPropertyException, ::com::sun::star::beans::PropertyVetoException, ::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::lang::WrappedTargetException, ::com::sun::star::uno::RuntimeException);
};

//==========================================================================

typedef ::cppu::WeakImplHelper1< NS_BEANS::XPropertySetInfo > SbPropertySetInfoHelper;

// AB 20.3.2000 Help Class for XPropertySetInfo implementation
class PropertySetInfoImpl
{
    friend class SbPropertySetInfo;
    friend class SbPropertyContainer;

    NS_UNO::Sequence< NS_BEANS::Property > _aProps;

    sal_Int32 GetIndex_Impl( const ::rtl::OUString &rPropName ) const;

public:
    PropertySetInfoImpl();
    PropertySetInfoImpl( NS_UNO::Sequence< NS_BEANS::Property >& rProps );

    // XPropertySetInfo
    NS_UNO::Sequence< NS_BEANS::Property > SAL_CALL getProperties(void) throw ();
    NS_BEANS::Property SAL_CALL getPropertyByName(const ::rtl::OUString& Name)
        throw( NS_UNO::RuntimeException );
    sal_Bool SAL_CALL hasPropertyByName(const ::rtl::OUString& Name)
        throw ( NS_UNO::RuntimeException );
};

class SbPropertySetInfo:    public SbPropertySetInfoHelper
{
    PropertySetInfoImpl aImpl;

public:
                            SbPropertySetInfo();
                            SbPropertySetInfo( const SbPropertyValueArr_Impl &rPropVals );
    virtual                 ~SbPropertySetInfo();

    // XPropertySetInfo
    virtual NS_UNO::Sequence< NS_BEANS::Property > SAL_CALL getProperties(void)
        throw( NS_UNO::RuntimeException );
    virtual NS_BEANS::Property SAL_CALL getPropertyByName(const ::rtl::OUString& Name)
        throw( NS_UNO::RuntimeException );
    virtual sal_Bool SAL_CALL hasPropertyByName(const ::rtl::OUString& Name)
        throw( NS_UNO::RuntimeException );
};

//==========================================================================

typedef ::cppu::WeakImplHelper2< NS_BEANS::XPropertySetInfo, NS_BEANS::XPropertyContainer > SbPropertyContainerHelper;

class SbPropertyContainer: public SbPropertyContainerHelper
{
    PropertySetInfoImpl aImpl;

public:
                            SbPropertyContainer();
    virtual                 ~SbPropertyContainer();

    // XPropertyContainer
    virtual void SAL_CALL addProperty(  const ::rtl::OUString& Name,
                                        INT16 Attributes,
                                        const NS_UNO::Any& DefaultValue)
        throw(  NS_BEANS::PropertyExistException, NS_BEANS::IllegalTypeException,
                NS_LANG::IllegalArgumentException, NS_UNO::RuntimeException );
    virtual void SAL_CALL removeProperty(const ::rtl::OUString& Name)
        throw( NS_BEANS::UnknownPropertyException, NS_UNO::RuntimeException );

    // XPropertySetInfo
    virtual NS_UNO::Sequence< NS_BEANS::Property > SAL_CALL getProperties(void) throw();
    virtual NS_BEANS::Property SAL_CALL getPropertyByName(const ::rtl::OUString& Name)
        throw( NS_UNO::RuntimeException );
    virtual sal_Bool SAL_CALL hasPropertyByName(const ::rtl::OUString& Name)
        throw( NS_UNO::RuntimeException );

    // XPropertyAccess
    virtual NS_UNO::Sequence< NS_BEANS::PropertyValue > SAL_CALL getPropertyValues(void);
    virtual void SAL_CALL setPropertyValues(const NS_UNO::Sequence< NS_BEANS::PropertyValue >& PropertyValues_);
};

//=========================================================================

class StarBASIC;
class SbxArray;

void RTL_Impl_CreatePropertySet( StarBASIC* pBasic, SbxArray& rPar, BOOL bWrite );

#undef NS_BEANS
#undef NS_LANG
#undef NS_UNO

#endif

<|endoftext|>


<commit_before>/*
 * Copyright (c) 2011, The University of Oxford
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 * 1. Redistributions of source code must retain the above copyright notice,
 *    this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright notice,
 *    this list of conditions and the following disclaimer in the documentation
 *    and/or other materials provided with the distribution.
 * 3. Neither the name of the University of Oxford nor the names of its
 *    contributors may be used to endorse or promote products derived from this
 *    software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 */

#include <mex.h>
#include "interferometry/oskar_Visibilities.h"
#include "utility/oskar_Mem.h"
#include "utility/oskar_vector_types.h"
#include "utility/oskar_get_error_string.h"
#include <cstdio>
#include <cstdlib>

void mexFunction(int num_out, mxArray** out, int num_in, const mxArray** in)
{
    if (num_in != 1 || num_out != 1)
        mexErrMsgTxt("Usage: vis = oskar_visibilities_read(filename)");

    // Extract arguments from MATLAB mxArray objects.
    const char* filename = mxArrayToString(in[0]);

    // Load the OSKAR visibilities structure from the specified file.
    int status = OSKAR_SUCCESS;
    oskar_Visibilities* vis = oskar_Visibilities::read(filename, &status);
    if (vis == NULL)
    {
        mexErrMsgIdAndTxt("OSKAR:error",
                "Error reading OSKAR visibilities data file: '%s'.\nERROR: %s.",
                filename, oskar_get_error_string(status));
    }

    if (vis->num_channels != 1)
        mexErrMsgTxt("Only one channel is currently supported");

    int num_times     = vis->num_times;
    int num_baselines = vis->num_baselines;
    int num_pols      = vis->num_polarisations();

    // Allocate memory returned to the MATLAB workspace.
    mwSize num_dims = 2;
    mwSize dims[2] = { num_baselines, num_times};
    mxClassID class_id = (vis->uu_metres.type() == OSKAR_DOUBLE) ?
            mxDOUBLE_CLASS : mxSINGLE_CLASS;
    mxArray* uu = mxCreateNumericArray(num_dims, dims, class_id, mxREAL);
    mxArray* vv = mxCreateNumericArray(num_dims, dims, class_id, mxREAL);
    mxArray* ww = mxCreateNumericArray(num_dims, dims, class_id, mxREAL);
    mxArray* xx = mxCreateNumericArray(num_dims, dims, class_id, mxCOMPLEX);
    mxArray *yy = NULL, *xy = NULL, *yx = NULL;
    mxArray *I = NULL, *Q = NULL, *U = NULL, *V = NULL;
    if (num_pols == 4)
    {
        xy = mxCreateNumericArray(num_dims, dims, class_id, mxCOMPLEX);
        yx = mxCreateNumericArray(num_dims, dims, class_id, mxCOMPLEX);
        yy = mxCreateNumericArray(num_dims, dims, class_id, mxCOMPLEX);
        I  = mxCreateNumericArray(num_dims, dims, class_id, mxCOMPLEX);
        Q  = mxCreateNumericArray(num_dims, dims, class_id, mxCOMPLEX);
        U  = mxCreateNumericArray(num_dims, dims, class_id, mxCOMPLEX);
        V  = mxCreateNumericArray(num_dims, dims, class_id, mxCOMPLEX);
    }

    mexPrintf("= Loading %i visibility samples\n",
            vis->num_times * vis->num_baselines);

    // Populate MATLAB arrays from the OSKAR visibilities structure.
    if (class_id == mxDOUBLE_CLASS)
    {
        double* uu_ptr    = (double*)mxGetPr(uu);
        double* vv_ptr    = (double*)mxGetPr(vv);
        double* ww_ptr    = (double*)mxGetPr(ww);
        double* xx_re_ptr = (double*)mxGetPr(xx);
        double* xx_im_ptr = (double*)mxGetPi(xx);
        double *xy_re_ptr = NULL, *xy_im_ptr = NULL;
        double *yx_re_ptr = NULL, *yx_im_ptr = NULL;
        double *yy_re_ptr = NULL, *yy_im_ptr = NULL;
        double *I_re_ptr  = NULL, *I_im_ptr = NULL;
        double *Q_re_ptr  = NULL, *Q_im_ptr = NULL;
        double *U_re_ptr  = NULL, *U_im_ptr = NULL;
        double *V_re_ptr  = NULL, *V_im_ptr = NULL;
        if (num_pols == 4)
        {
            xy_re_ptr = (double*)mxGetPr(xy);
            xy_im_ptr = (double*)mxGetPi(xy);
            yx_re_ptr = (double*)mxGetPr(yx);
            yx_im_ptr = (double*)mxGetPi(yx);
            yy_re_ptr = (double*)mxGetPr(yy);
            yy_im_ptr = (double*)mxGetPi(yy);
            I_re_ptr  = (double*)mxGetPr(I);
            I_im_ptr  = (double*)mxGetPi(I);
            Q_re_ptr  = (double*)mxGetPr(Q);
            Q_im_ptr  = (double*)mxGetPi(Q);
            U_re_ptr  = (double*)mxGetPr(U);
            U_im_ptr  = (double*)mxGetPi(U);
            V_re_ptr  = (double*)mxGetPr(V);
            V_im_ptr  = (double*)mxGetPi(V);
        }
        for (int i = 0; i < vis->num_times * vis->num_baselines; ++i)
        {
            uu_ptr[i] = ((double*)(vis->uu_metres.data))[i];
            vv_ptr[i] = ((double*)(vis->vv_metres.data))[i];
            ww_ptr[i] = ((double*)(vis->ww_metres.data))[i];

            if (num_pols == 1)
            {
                xx_re_ptr[i] = ((double2*)(vis->amplitude.data))[i].x;
                xx_im_ptr[i] = ((double2*)(vis->amplitude.data))[i].y;
            }
            else
            {
                xx_re_ptr[i] = ((double4c*)(vis->amplitude.data))[i].a.x;
                xx_im_ptr[i] = ((double4c*)(vis->amplitude.data))[i].a.y;
                xy_re_ptr[i] = ((double4c*)(vis->amplitude.data))[i].b.x;
                xy_im_ptr[i] = ((double4c*)(vis->amplitude.data))[i].b.y;
                yx_re_ptr[i] = ((double4c*)(vis->amplitude.data))[i].c.x;
                yx_im_ptr[i] = ((double4c*)(vis->amplitude.data))[i].c.y;
                yy_re_ptr[i] = ((double4c*)(vis->amplitude.data))[i].d.x;
                yy_im_ptr[i] = ((double4c*)(vis->amplitude.data))[i].d.y;

                // I = 0.5 (XX + YY)
                I_re_ptr[i]  = 0.5 * (xx_re_ptr[i] + yy_re_ptr[i]);
                I_im_ptr[i]  = 0.5 * (xx_im_ptr[i] + yy_im_ptr[i]);

                // Q = 0.5 (XX - YY)
                Q_re_ptr[i]  = 0.5 * (xx_re_ptr[i] - yy_re_ptr[i]);
                Q_im_ptr[i]  = 0.5 * (xx_im_ptr[i] - yy_im_ptr[i]);

                // U = 0.5 (XY + YX)
                U_re_ptr[i]  = 0.5 * (xy_re_ptr[i] + yx_re_ptr[i]);
                U_im_ptr[i]  = 0.5 * (xy_im_ptr[i] + yx_im_ptr[i]);

                // U = -0.5i (XY - YX)
                V_re_ptr[i]  = -0.5 * (xx_im_ptr[i] - yy_im_ptr[i]);
                V_im_ptr[i]  =  0.5 * (xx_re_ptr[i] - yy_re_ptr[i]);
            }
        }
    }
    else
    {
        float* uu_ptr    = (float*)mxGetPr(uu);
        float* vv_ptr    = (float*)mxGetPr(vv);
        float* ww_ptr    = (float*)mxGetPr(ww);
        float* xx_re_ptr = (float*)mxGetPr(xx);
        float* xx_im_ptr = (float*)mxGetPi(xx);
        float *xy_re_ptr = NULL, *xy_im_ptr = NULL;
        float *yx_re_ptr = NULL, *yx_im_ptr = NULL;
        float *yy_re_ptr = NULL, *yy_im_ptr = NULL;
        float *I_re_ptr  = NULL, *I_im_ptr = NULL;
        float *Q_re_ptr  = NULL, *Q_im_ptr = NULL;
        float *U_re_ptr  = NULL, *U_im_ptr = NULL;
        float *V_re_ptr  = NULL, *V_im_ptr = NULL;
        if (num_pols == 4)
        {
            xy_re_ptr = (float*)mxGetPr(xy);
            xy_im_ptr = (float*)mxGetPi(xy);
            yx_re_ptr = (float*)mxGetPr(yx);
            yx_im_ptr = (float*)mxGetPi(yx);
            yy_re_ptr = (float*)mxGetPr(yy);
            yy_im_ptr = (float*)mxGetPi(yy);
            I_re_ptr  = (float*)mxGetPr(I);
            I_im_ptr  = (float*)mxGetPi(I);
            Q_re_ptr  = (float*)mxGetPr(Q);
            Q_im_ptr  = (float*)mxGetPi(Q);
            U_re_ptr  = (float*)mxGetPr(U);
            U_im_ptr  = (float*)mxGetPi(U);
            V_re_ptr  = (float*)mxGetPr(V);
            V_im_ptr  = (float*)mxGetPi(V);

        }
        for (int i = 0; i < vis->num_times * vis->num_baselines; ++i)
        {
            uu_ptr[i] = ((float*)(vis->uu_metres.data))[i];
            vv_ptr[i] = ((float*)(vis->vv_metres.data))[i];
            ww_ptr[i] = ((float*)(vis->ww_metres.data))[i];

            if (num_pols == 1)
            {
                xx_re_ptr[i] = ((float2*)(vis->amplitude.data))[i].x;
                xx_im_ptr[i] = ((float2*)(vis->amplitude.data))[i].y;
            }
            else
            {
                xx_re_ptr[i] = ((float4c*)(vis->amplitude.data))[i].a.x;
                xx_im_ptr[i] = ((float4c*)(vis->amplitude.data))[i].a.y;
                xy_re_ptr[i] = ((float4c*)(vis->amplitude.data))[i].b.x;
                xy_im_ptr[i] = ((float4c*)(vis->amplitude.data))[i].b.y;
                yx_re_ptr[i] = ((float4c*)(vis->amplitude.data))[i].c.x;
                yx_im_ptr[i] = ((float4c*)(vis->amplitude.data))[i].c.y;
                yy_re_ptr[i] = ((float4c*)(vis->amplitude.data))[i].d.x;
                yy_im_ptr[i] = ((float4c*)(vis->amplitude.data))[i].d.y;

                // I = 0.5 (XX + YY)
                I_re_ptr[i]  = 0.5 * (xx_re_ptr[i] + yy_re_ptr[i]);
                I_im_ptr[i]  = 0.5 * (xx_im_ptr[i] + yy_im_ptr[i]);

                // Q = 0.5 (XX - YY)
                Q_re_ptr[i]  = 0.5 * (xx_re_ptr[i] - yy_re_ptr[i]);
                Q_im_ptr[i]  = 0.5 * (xx_im_ptr[i] - yy_im_ptr[i]);

                // U = 0.5 (XY + YX)
                U_re_ptr[i]  = 0.5 * (xy_re_ptr[i] + yx_re_ptr[i]);
                U_im_ptr[i]  = 0.5 * (xy_im_ptr[i] + yx_im_ptr[i]);

                // U = -0.5i (XY - YX)
                V_re_ptr[i]  = -0.5 * (xx_im_ptr[i] - yy_im_ptr[i]);
                V_im_ptr[i]  =  0.5 * (xx_re_ptr[i] - yy_re_ptr[i]);
            }
        }
    }

    // Create and populate output visibility structure.
    if (num_pols == 4)
    {
        const char* fields[11] = {"uu", "vv", "ww", "xx", "xy", "yx", "yy",
                "I", "Q", "U", "V"};
        out[0] = mxCreateStructMatrix(1, 1, 11, fields);
    }
    else
    {
        const char* fields[4] = {"uu", "vv", "ww", "xx"};
        out[0] = mxCreateStructMatrix(1, 1, 4, fields);
    }
    mxSetField(out[0], 0, "uu", uu);
    mxSetField(out[0], 0, "vv", vv);
    mxSetField(out[0], 0, "ww", ww);
    mxSetField(out[0], 0, "xx", xx);
    if (num_pols == 4)
    {
        mxSetField(out[0], 0, "xy", xy);
        mxSetField(out[0], 0, "yx", yx);
        mxSetField(out[0], 0, "yy", yy);
        mxSetField(out[0], 0, "I", I);
        mxSetField(out[0], 0, "Q", Q);
        mxSetField(out[0], 0, "U", U);
        mxSetField(out[0], 0, "V", V);
    }

    // Clean up local memory.
    delete vis;
}
<commit_msg>updated mex visibility loader to work with multiple channels and the new vis data format<commit_after>/*
 * Copyright (c) 2011, The University of Oxford
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 * 1. Redistributions of source code must retain the above copyright notice,
 *    this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright notice,
 *    this list of conditions and the following disclaimer in the documentation
 *    and/or other materials provided with the distribution.
 * 3. Neither the name of the University of Oxford nor the names of its
 *    contributors may be used to endorse or promote products derived from this
 *    software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 */

#include <mex.h>
#include "interferometry/oskar_Visibilities.h"
#include "utility/oskar_Mem.h"
#include "utility/oskar_vector_types.h"
#include "utility/oskar_get_error_string.h"
#include <cstdio>
#include <cstdlib>

void mexFunction(int num_out, mxArray** out, int num_in, const mxArray** in)
{
    if (num_in != 1 || num_out != 1)
        mexErrMsgTxt("Usage: vis = oskar_visibilities_read(filename)");

    // Extract arguments from MATLAB mxArray objects.
    const char* filename = mxArrayToString(in[0]);

    // Load the OSKAR visibilities structure from the specified file.
    int status = OSKAR_SUCCESS;
    oskar_Visibilities* vis = oskar_Visibilities::read(filename, &status);
    if (vis == NULL)
    {
        mexErrMsgIdAndTxt("OSKAR:error",
                "Error reading OSKAR visibilities data file: '%s'.\nERROR: %s.",
                filename, oskar_get_error_string(status));
    }

    int num_channels  = vis->num_channels;
    int num_times     = vis->num_times;
    int num_baselines = vis->num_baselines;
    int num_pols      = vis->num_polarisations();

    // Allocate memory returned to the MATLAB work-space.
    mwSize coord_dims[2] = { num_baselines, num_times};
    mwSize amp_dims[3]   = {num_baselines, num_times, num_channels};
    mxClassID class_id = (vis->uu_metres.type() == OSKAR_DOUBLE) ?
            mxDOUBLE_CLASS : mxSINGLE_CLASS;
    mxArray* uu = mxCreateNumericArray(2, coord_dims, class_id, mxREAL);
    mxArray* vv = mxCreateNumericArray(2, coord_dims, class_id, mxREAL);
    mxArray* ww = mxCreateNumericArray(2, coord_dims, class_id, mxREAL);
    mxArray* xx = mxCreateNumericArray(3, amp_dims, class_id, mxCOMPLEX);
    mxArray *yy = NULL, *xy = NULL, *yx = NULL;
    mxArray *I = NULL, *Q = NULL, *U = NULL, *V = NULL;
    if (num_pols == 4)
    {
        xy = mxCreateNumericArray(3, amp_dims, class_id, mxCOMPLEX);
        yx = mxCreateNumericArray(3, amp_dims, class_id, mxCOMPLEX);
        yy = mxCreateNumericArray(3, amp_dims, class_id, mxCOMPLEX);
        I  = mxCreateNumericArray(3, amp_dims, class_id, mxCOMPLEX);
        Q  = mxCreateNumericArray(3, amp_dims, class_id, mxCOMPLEX);
        U  = mxCreateNumericArray(3, amp_dims, class_id, mxCOMPLEX);
        V  = mxCreateNumericArray(3, amp_dims, class_id, mxCOMPLEX);
    }

    mexPrintf("= Loading %i visibility samples\n",
            vis->num_times * vis->num_baselines);

    // Populate MATLAB arrays from the OSKAR visibilities structure.
    if (class_id == mxDOUBLE_CLASS)
    {
        double* uu_ptr    = (double*)mxGetPr(uu);
        double* vv_ptr    = (double*)mxGetPr(vv);
        double* ww_ptr    = (double*)mxGetPr(ww);
        double* xx_re_ptr = (double*)mxGetPr(xx);
        double* xx_im_ptr = (double*)mxGetPi(xx);
        double *xy_re_ptr = NULL, *xy_im_ptr = NULL;
        double *yx_re_ptr = NULL, *yx_im_ptr = NULL;
        double *yy_re_ptr = NULL, *yy_im_ptr = NULL;
        double *I_re_ptr  = NULL, *I_im_ptr = NULL;
        double *Q_re_ptr  = NULL, *Q_im_ptr = NULL;
        double *U_re_ptr  = NULL, *U_im_ptr = NULL;
        double *V_re_ptr  = NULL, *V_im_ptr = NULL;
        if (num_pols == 4)
        {
            xy_re_ptr = (double*)mxGetPr(xy);
            xy_im_ptr = (double*)mxGetPi(xy);
            yx_re_ptr = (double*)mxGetPr(yx);
            yx_im_ptr = (double*)mxGetPi(yx);
            yy_re_ptr = (double*)mxGetPr(yy);
            yy_im_ptr = (double*)mxGetPi(yy);
            I_re_ptr  = (double*)mxGetPr(I);
            I_im_ptr  = (double*)mxGetPi(I);
            Q_re_ptr  = (double*)mxGetPr(Q);
            Q_im_ptr  = (double*)mxGetPi(Q);
            U_re_ptr  = (double*)mxGetPr(U);
            U_im_ptr  = (double*)mxGetPi(U);
            V_re_ptr  = (double*)mxGetPr(V);
            V_im_ptr  = (double*)mxGetPi(V);
        }
        for (int i = 0; i < num_times * num_baselines; ++i)
        {
            uu_ptr[i] = ((double*)(vis->uu_metres.data))[i];
            vv_ptr[i] = ((double*)(vis->vv_metres.data))[i];
            ww_ptr[i] = ((double*)(vis->ww_metres.data))[i];
        }

        for (int i = 0; i < num_channels * num_times * num_baselines; ++i)
        {

            if (num_pols == 1)
            {
                xx_re_ptr[i] = ((double2*)(vis->amplitude.data))[i].x;
                xx_im_ptr[i] = ((double2*)(vis->amplitude.data))[i].y;
            }
            else
            {
                xx_re_ptr[i] = ((double4c*)(vis->amplitude.data))[i].a.x;
                xx_im_ptr[i] = ((double4c*)(vis->amplitude.data))[i].a.y;
                xy_re_ptr[i] = ((double4c*)(vis->amplitude.data))[i].b.x;
                xy_im_ptr[i] = ((double4c*)(vis->amplitude.data))[i].b.y;
                yx_re_ptr[i] = ((double4c*)(vis->amplitude.data))[i].c.x;
                yx_im_ptr[i] = ((double4c*)(vis->amplitude.data))[i].c.y;
                yy_re_ptr[i] = ((double4c*)(vis->amplitude.data))[i].d.x;
                yy_im_ptr[i] = ((double4c*)(vis->amplitude.data))[i].d.y;

                // I = 0.5 (XX + YY)
                I_re_ptr[i]  = 0.5 * (xx_re_ptr[i] + yy_re_ptr[i]);
                I_im_ptr[i]  = 0.5 * (xx_im_ptr[i] + yy_im_ptr[i]);

                // Q = 0.5 (XX - YY)
                Q_re_ptr[i]  = 0.5 * (xx_re_ptr[i] - yy_re_ptr[i]);
                Q_im_ptr[i]  = 0.5 * (xx_im_ptr[i] - yy_im_ptr[i]);

                // U = 0.5 (XY + YX)
                U_re_ptr[i]  = 0.5 * (xy_re_ptr[i] + yx_re_ptr[i]);
                U_im_ptr[i]  = 0.5 * (xy_im_ptr[i] + yx_im_ptr[i]);

                // U = -0.5i (XY - YX)
                V_re_ptr[i]  = -0.5 * (xx_im_ptr[i] - yy_im_ptr[i]);
                V_im_ptr[i]  =  0.5 * (xx_re_ptr[i] - yy_re_ptr[i]);
            }
        }
    }
    else
    {
        float* uu_ptr    = (float*)mxGetPr(uu);
        float* vv_ptr    = (float*)mxGetPr(vv);
        float* ww_ptr    = (float*)mxGetPr(ww);
        float* xx_re_ptr = (float*)mxGetPr(xx);
        float* xx_im_ptr = (float*)mxGetPi(xx);
        float *xy_re_ptr = NULL, *xy_im_ptr = NULL;
        float *yx_re_ptr = NULL, *yx_im_ptr = NULL;
        float *yy_re_ptr = NULL, *yy_im_ptr = NULL;
        float *I_re_ptr  = NULL, *I_im_ptr = NULL;
        float *Q_re_ptr  = NULL, *Q_im_ptr = NULL;
        float *U_re_ptr  = NULL, *U_im_ptr = NULL;
        float *V_re_ptr  = NULL, *V_im_ptr = NULL;
        if (num_pols == 4)
        {
            xy_re_ptr = (float*)mxGetPr(xy);
            xy_im_ptr = (float*)mxGetPi(xy);
            yx_re_ptr = (float*)mxGetPr(yx);
            yx_im_ptr = (float*)mxGetPi(yx);
            yy_re_ptr = (float*)mxGetPr(yy);
            yy_im_ptr = (float*)mxGetPi(yy);
            I_re_ptr  = (float*)mxGetPr(I);
            I_im_ptr  = (float*)mxGetPi(I);
            Q_re_ptr  = (float*)mxGetPr(Q);
            Q_im_ptr  = (float*)mxGetPi(Q);
            U_re_ptr  = (float*)mxGetPr(U);
            U_im_ptr  = (float*)mxGetPi(U);
            V_re_ptr  = (float*)mxGetPr(V);
            V_im_ptr  = (float*)mxGetPi(V);

        }

        for (int i = 0; i < num_times * num_baselines; ++i)
        {
            uu_ptr[i] = ((float*)(vis->uu_metres.data))[i];
            vv_ptr[i] = ((float*)(vis->vv_metres.data))[i];
            ww_ptr[i] = ((float*)(vis->ww_metres.data))[i];
        }

        for (int i = 0; i < num_channels * num_times * num_baselines; ++i)
        {

            if (num_pols == 1)
            {
                xx_re_ptr[i] = ((float2*)(vis->amplitude.data))[i].x;
                xx_im_ptr[i] = ((float2*)(vis->amplitude.data))[i].y;
            }
            else
            {
                xx_re_ptr[i] = ((float4c*)(vis->amplitude.data))[i].a.x;
                xx_im_ptr[i] = ((float4c*)(vis->amplitude.data))[i].a.y;
                xy_re_ptr[i] = ((float4c*)(vis->amplitude.data))[i].b.x;
                xy_im_ptr[i] = ((float4c*)(vis->amplitude.data))[i].b.y;
                yx_re_ptr[i] = ((float4c*)(vis->amplitude.data))[i].c.x;
                yx_im_ptr[i] = ((float4c*)(vis->amplitude.data))[i].c.y;
                yy_re_ptr[i] = ((float4c*)(vis->amplitude.data))[i].d.x;
                yy_im_ptr[i] = ((float4c*)(vis->amplitude.data))[i].d.y;

                // I = 0.5 (XX + YY)
                I_re_ptr[i]  = 0.5 * (xx_re_ptr[i] + yy_re_ptr[i]);
                I_im_ptr[i]  = 0.5 * (xx_im_ptr[i] + yy_im_ptr[i]);

                // Q = 0.5 (XX - YY)
                Q_re_ptr[i]  = 0.5 * (xx_re_ptr[i] - yy_re_ptr[i]);
                Q_im_ptr[i]  = 0.5 * (xx_im_ptr[i] - yy_im_ptr[i]);

                // U = 0.5 (XY + YX)
                U_re_ptr[i]  = 0.5 * (xy_re_ptr[i] + yx_re_ptr[i]);
                U_im_ptr[i]  = 0.5 * (xy_im_ptr[i] + yx_im_ptr[i]);

                // U = -0.5i (XY - YX)
                V_re_ptr[i]  = -0.5 * (xx_im_ptr[i] - yy_im_ptr[i]);
                V_im_ptr[i]  =  0.5 * (xx_re_ptr[i] - yy_re_ptr[i]);
            }
        }
    }

    // Create and populate output visibility structure.
    if (num_pols == 4)
    {
        const char* fields[11] = {"uu_metres", "vv_metres", "ww_metres",
                "xx", "xy", "yx", "yy", "I", "Q", "U", "V"};
        out[0] = mxCreateStructMatrix(1, 1, 11, fields);
    }
    else
    {
        const char* fields[4] = {"uu_metres", "vv_metres", "ww_metres",
                "xx"};
        out[0] = mxCreateStructMatrix(1, 1, 4, fields);
    }
    mxSetField(out[0], 0, "uu_metres", uu);
    mxSetField(out[0], 0, "vv_metres", vv);
    mxSetField(out[0], 0, "ww_metres", ww);
    mxSetField(out[0], 0, "xx", xx);
    if (num_pols == 4)
    {
        mxSetField(out[0], 0, "xy", xy);
        mxSetField(out[0], 0, "yx", yx);
        mxSetField(out[0], 0, "yy", yy);
        mxSetField(out[0], 0, "I", I);
        mxSetField(out[0], 0, "Q", Q);
        mxSetField(out[0], 0, "U", U);
        mxSetField(out[0], 0, "V", V);
    }

    // Clean up local memory.
    delete vis;
}
<|endoftext|>


<commit_before>//===------ SimplifyInstructions.cpp - Remove redundant instructions ------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This is a utility pass used for testing the InstructionSimplify analysis.
// The analysis is applied to every instruction, and if it simplifies then the
// instruction is replaced by the simplification.  If you are looking for a pass
// that performs serious instruction folding, use the instcombine pass instead.
//
//===----------------------------------------------------------------------===//

#include "llvm/Transforms/Utils/SimplifyInstructions.h"
#include "llvm/ADT/DepthFirstIterator.h"
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/ADT/Statistic.h"
#include "llvm/Analysis/AssumptionCache.h"
#include "llvm/Analysis/InstructionSimplify.h"
#include "llvm/Analysis/OptimizationDiagnosticInfo.h"
#include "llvm/Analysis/TargetLibraryInfo.h"
#include "llvm/IR/DataLayout.h"
#include "llvm/IR/Dominators.h"
#include "llvm/IR/Function.h"
#include "llvm/IR/Type.h"
#include "llvm/Pass.h"
#include "llvm/Transforms/Utils/Local.h"
#include "llvm/Transforms/Scalar.h"
using namespace llvm;

#define DEBUG_TYPE "instsimplify"

STATISTIC(NumSimplified, "Number of redundant instructions removed");

static bool runImpl(Function &F, const DominatorTree *DT,
                    const TargetLibraryInfo *TLI, AssumptionCache *AC,
                    OptimizationRemarkEmitter *ORE) {
  const DataLayout &DL = F.getParent()->getDataLayout();
  SmallPtrSet<const Instruction *, 8> S1, S2, *ToSimplify = &S1, *Next = &S2;
  bool Changed = false;

  do {
    for (BasicBlock *BB : depth_first(&F.getEntryBlock())) {
      // Here be subtlety: the iterator must be incremented before the loop
      // body (not sure why), so a range-for loop won't work here.
      for (BasicBlock::iterator BI = BB->begin(), BE = BB->end(); BI != BE;) {
        Instruction *I = &*BI++;
        // The first time through the loop ToSimplify is empty and we try to
        // simplify all instructions.  On later iterations ToSimplify is not
        // empty and we only bother simplifying instructions that are in it.
        if (!ToSimplify->empty() && !ToSimplify->count(I))
          continue;

        // Don't waste time simplifying unused instructions.
        if (!I->use_empty()) {
          if (Value *V = SimplifyInstruction(I, DL, TLI, DT, AC, ORE)) {
            // Mark all uses for resimplification next time round the loop.
            for (User *U : I->users())
              Next->insert(cast<Instruction>(U));
            I->replaceAllUsesWith(V);
            ++NumSimplified;
            Changed = true;
          }
        }
        if (RecursivelyDeleteTriviallyDeadInstructions(I, TLI)) {
          // RecursivelyDeleteTriviallyDeadInstruction can remove more than one
          // instruction, so simply incrementing the iterator does not work.
          // When instructions get deleted re-iterate instead.
          BI = BB->begin();
          BE = BB->end();
          Changed = true;
        }
      }
    }

    // Place the list of instructions to simplify on the next loop iteration
    // into ToSimplify.
    std::swap(ToSimplify, Next);
    Next->clear();
  } while (!ToSimplify->empty());

  return Changed;
}

namespace {
  struct InstSimplifier : public FunctionPass {
    static char ID; // Pass identification, replacement for typeid
    InstSimplifier() : FunctionPass(ID) {
      initializeInstSimplifierPass(*PassRegistry::getPassRegistry());
    }

    void getAnalysisUsage(AnalysisUsage &AU) const override {
      AU.setPreservesCFG();
      AU.addRequired<DominatorTreeWrapperPass>();
      AU.addRequired<AssumptionCacheTracker>();
      AU.addRequired<TargetLibraryInfoWrapperPass>();
      AU.addRequired<OptimizationRemarkEmitterWrapperPass>();
    }

    /// runOnFunction - Remove instructions that simplify.
    bool runOnFunction(Function &F) override {
      if (skipFunction(F))
        return false;

      const DominatorTree *DT =
          &getAnalysis<DominatorTreeWrapperPass>().getDomTree();
      const TargetLibraryInfo *TLI =
          &getAnalysis<TargetLibraryInfoWrapperPass>().getTLI();
      AssumptionCache *AC =
          &getAnalysis<AssumptionCacheTracker>().getAssumptionCache(F);
      OptimizationRemarkEmitter *ORE =
          &getAnalysis<OptimizationRemarkEmitterWrapperPass>().getORE();

      return runImpl(F, DT, TLI, AC, ORE);
    }
  };
}

char InstSimplifier::ID = 0;
INITIALIZE_PASS_BEGIN(InstSimplifier, "instsimplify",
                      "Remove redundant instructions", false, false)
INITIALIZE_PASS_DEPENDENCY(AssumptionCacheTracker)
INITIALIZE_PASS_DEPENDENCY(DominatorTreeWrapperPass)
INITIALIZE_PASS_DEPENDENCY(TargetLibraryInfoWrapperPass)
INITIALIZE_PASS_DEPENDENCY(OptimizationRemarkEmitterWrapperPass)
INITIALIZE_PASS_END(InstSimplifier, "instsimplify",
                    "Remove redundant instructions", false, false)
char &llvm::InstructionSimplifierID = InstSimplifier::ID;

// Public interface to the simplify instructions pass.
FunctionPass *llvm::createInstructionSimplifierPass() {
  return new InstSimplifier();
}

PreservedAnalyses InstSimplifierPass::run(Function &F,
                                      FunctionAnalysisManager &AM) {
  auto &DT = AM.getResult<DominatorTreeAnalysis>(F);
  auto &TLI = AM.getResult<TargetLibraryAnalysis>(F);
  auto &AC = AM.getResult<AssumptionAnalysis>(F);
  auto &ORE = AM.getResult<OptimizationRemarkEmitterAnalysis>(F);
  bool Changed = runImpl(F, &DT, &TLI, &AC, &ORE);
  if (!Changed)
    return PreservedAnalyses::all();

  PreservedAnalyses PA;
  PA.preserveSet<CFGAnalyses>();
  return PA;
}
<commit_msg>Convert SimplifyInstructions to use the SimplifyQuery version of SimplifyInstruction<commit_after>//===------ SimplifyInstructions.cpp - Remove redundant instructions ------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This is a utility pass used for testing the InstructionSimplify analysis.
// The analysis is applied to every instruction, and if it simplifies then the
// instruction is replaced by the simplification.  If you are looking for a pass
// that performs serious instruction folding, use the instcombine pass instead.
//
//===----------------------------------------------------------------------===//

#include "llvm/Transforms/Utils/SimplifyInstructions.h"
#include "llvm/ADT/DepthFirstIterator.h"
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/ADT/Statistic.h"
#include "llvm/Analysis/AssumptionCache.h"
#include "llvm/Analysis/InstructionSimplify.h"
#include "llvm/Analysis/OptimizationDiagnosticInfo.h"
#include "llvm/Analysis/TargetLibraryInfo.h"
#include "llvm/IR/DataLayout.h"
#include "llvm/IR/Dominators.h"
#include "llvm/IR/Function.h"
#include "llvm/IR/Type.h"
#include "llvm/Pass.h"
#include "llvm/Transforms/Utils/Local.h"
#include "llvm/Transforms/Scalar.h"
using namespace llvm;

#define DEBUG_TYPE "instsimplify"

STATISTIC(NumSimplified, "Number of redundant instructions removed");

static bool runImpl(Function &F, const SimplifyQuery &SQ,
                    OptimizationRemarkEmitter *ORE) {
  SmallPtrSet<const Instruction *, 8> S1, S2, *ToSimplify = &S1, *Next = &S2;
  bool Changed = false;

  do {
    for (BasicBlock *BB : depth_first(&F.getEntryBlock())) {
      // Here be subtlety: the iterator must be incremented before the loop
      // body (not sure why), so a range-for loop won't work here.
      for (BasicBlock::iterator BI = BB->begin(), BE = BB->end(); BI != BE;) {
        Instruction *I = &*BI++;
        // The first time through the loop ToSimplify is empty and we try to
        // simplify all instructions.  On later iterations ToSimplify is not
        // empty and we only bother simplifying instructions that are in it.
        if (!ToSimplify->empty() && !ToSimplify->count(I))
          continue;

        // Don't waste time simplifying unused instructions.
        if (!I->use_empty()) {
          if (Value *V =
                  SimplifyInstruction(I, SQ.getWithInstruction(I), ORE)) {
            // Mark all uses for resimplification next time round the loop.
            for (User *U : I->users())
              Next->insert(cast<Instruction>(U));
            I->replaceAllUsesWith(V);
            ++NumSimplified;
            Changed = true;
          }
        }
        if (RecursivelyDeleteTriviallyDeadInstructions(I, SQ.TLI)) {
          // RecursivelyDeleteTriviallyDeadInstruction can remove more than one
          // instruction, so simply incrementing the iterator does not work.
          // When instructions get deleted re-iterate instead.
          BI = BB->begin();
          BE = BB->end();
          Changed = true;
        }
      }
    }

    // Place the list of instructions to simplify on the next loop iteration
    // into ToSimplify.
    std::swap(ToSimplify, Next);
    Next->clear();
  } while (!ToSimplify->empty());

  return Changed;
}

namespace {
  struct InstSimplifier : public FunctionPass {
    static char ID; // Pass identification, replacement for typeid
    InstSimplifier() : FunctionPass(ID) {
      initializeInstSimplifierPass(*PassRegistry::getPassRegistry());
    }

    void getAnalysisUsage(AnalysisUsage &AU) const override {
      AU.setPreservesCFG();
      AU.addRequired<DominatorTreeWrapperPass>();
      AU.addRequired<AssumptionCacheTracker>();
      AU.addRequired<TargetLibraryInfoWrapperPass>();
      AU.addRequired<OptimizationRemarkEmitterWrapperPass>();
    }

    /// runOnFunction - Remove instructions that simplify.
    bool runOnFunction(Function &F) override {
      if (skipFunction(F))
        return false;

      const DominatorTree *DT =
          &getAnalysis<DominatorTreeWrapperPass>().getDomTree();
      const TargetLibraryInfo *TLI =
          &getAnalysis<TargetLibraryInfoWrapperPass>().getTLI();
      AssumptionCache *AC =
          &getAnalysis<AssumptionCacheTracker>().getAssumptionCache(F);
      OptimizationRemarkEmitter *ORE =
          &getAnalysis<OptimizationRemarkEmitterWrapperPass>().getORE();
      const DataLayout &DL = F.getParent()->getDataLayout();
      const SimplifyQuery SQ(DL, TLI, DT, AC);
      return runImpl(F, SQ, ORE);
    }
  };
}

char InstSimplifier::ID = 0;
INITIALIZE_PASS_BEGIN(InstSimplifier, "instsimplify",
                      "Remove redundant instructions", false, false)
INITIALIZE_PASS_DEPENDENCY(AssumptionCacheTracker)
INITIALIZE_PASS_DEPENDENCY(DominatorTreeWrapperPass)
INITIALIZE_PASS_DEPENDENCY(TargetLibraryInfoWrapperPass)
INITIALIZE_PASS_DEPENDENCY(OptimizationRemarkEmitterWrapperPass)
INITIALIZE_PASS_END(InstSimplifier, "instsimplify",
                    "Remove redundant instructions", false, false)
char &llvm::InstructionSimplifierID = InstSimplifier::ID;

// Public interface to the simplify instructions pass.
FunctionPass *llvm::createInstructionSimplifierPass() {
  return new InstSimplifier();
}

PreservedAnalyses InstSimplifierPass::run(Function &F,
                                      FunctionAnalysisManager &AM) {
  auto &DT = AM.getResult<DominatorTreeAnalysis>(F);
  auto &TLI = AM.getResult<TargetLibraryAnalysis>(F);
  auto &AC = AM.getResult<AssumptionAnalysis>(F);
  auto &ORE = AM.getResult<OptimizationRemarkEmitterAnalysis>(F);
  const DataLayout &DL = F.getParent()->getDataLayout();
  const SimplifyQuery SQ(DL, &TLI, &DT, &AC);
  bool Changed = runImpl(F, SQ, &ORE);
  if (!Changed)
    return PreservedAnalyses::all();

  PreservedAnalyses PA;
  PA.preserveSet<CFGAnalyses>();
  return PA;
}
<|endoftext|>