<commit_before>/** \brief Utility for deleting partial or entire MARC records based on an input list.
 *  \author Dr. Johannes Ruscheinski (johannes.ruscheinski@uni-tuebingen.de)
 *
 *  \copyright 2015 Universitätsbiblothek Tübingen.  All rights reserved.
 *
 *  This program is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU Affero General Public License as
 *  published by the Free Software Foundation, either version 3 of the
 *  License, or (at your option) any later version.
 *
 *  This program 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 Affero General Public License for more details.
 *
 *  You should have received a copy of the GNU Affero General Public License
 *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/

#include <algorithm>
#include <iostream>
#include <memory>
#include <stdexcept>
#include <unordered_set>
#include <vector>
#include <cstdio>
#include <cstdlib>
#include "Compiler.h"
#include "MarcUtil.h"
#include "StringUtil.h"
#include "Subfields.h"
#include "util.h"

static void Usage() __attribute__((noreturn));

static void Usage() {
    std::cerr << "Usage: " << progname << " deletion_list input_marc output_marc\n";
    std::exit(EXIT_FAILURE);
}

void ExtractDeletionIds(File *const deletion_list, std::unordered_set <std::string> * const title_deletion_ids,
                        std::unordered_set <std::string> *const local_deletion_ids) {
    unsigned line_no(0);
    while (not deletion_list->eof()) {
	const std::string line(StringUtil::Trim(deletion_list->getline()));
        ++line_no;
	if (unlikely(line.empty())) // Ignore empty lines.
	    continue;
        if (line.length() < 12)
            Error("short line in deletion list file: \"" + line + "\"!");
        if (line[11] == 'A')
            title_deletion_ids->insert(line.substr(12)); // extract PPN
        else if (line[11] == '9') {
            if (line.length() != 25)
                Error("unexpected line length for local entry on line " + std::to_string(line_no) + "!");
            local_deletion_ids->insert(line.substr(12, 9)); // extract ELN
        }
    }
}

int MatchLocalID(const std::unordered_set <std::string> &local_ids, const std::vector <DirectoryEntry> &dir_entries,
                 const std::vector <std::string> &field_data) {
    for (size_t i(0); i < dir_entries.size(); ++i) {
        if (dir_entries[i].getTag() != "LOK")
            continue;

        const Subfields subfields(field_data[i]);
        if (not subfields.hasSubfield('0'))
            continue;

        const std::string subfield_contents(subfields.getFirstSubfieldValue('0'));
        if (not StringUtil::StartsWith(subfield_contents, "001 ")
            or local_ids.find(subfield_contents.substr(4)) == local_ids.end())
            continue;

        return i;
    }

    return -1;
}

class MatchTag {
    const std::string tag_to_match_;
public:
    explicit MatchTag(const std::string &tag_to_match) : tag_to_match_(tag_to_match) { }

    bool operator()(const DirectoryEntry &dir_entry) const { return dir_entry.getTag() == tag_to_match_; }
};

/** \brief Deletes LOK sections if their pseudo tags are found in "local_deletion_ids"
 *  \return True if at least one local section has been deleted, else false.
 */
bool DeleteLocalSections(const std::vector<DirectoryEntry> &dir_entries, const std::vector<std::string> &fields,
			 const std::unordered_set <std::string> &local_deletion_ids, MarcUtil::Record * const record)
{
    bool modified(false);

    ssize_t start_local_match;
    while ((start_local_match = MatchLocalID(local_deletion_ids, dir_entries, fields)) != -1) {
	// We now expect a field "000" before the current "001" field.  (This is just a sanity check!):
	--start_local_match;
	if (start_local_match <= 0)
	    Error("weird data structure (1)!");
	const Subfields subfields1(fields[start_local_match]);
	if (not subfields1.hasSubfield('0')
	    or not StringUtil::StartsWith(subfields1.getFirstSubfieldValue('0'), "000 "))
	    Error("missing or empty local field \"000\"! (EPN: "
		  + fields[start_local_match + 1].substr(8) + ", PPN: " + fields[0] + ")");

	// Now we need to find the index one past the end of the local record.  This would
	// be either the "000" field of the next local record or one past the end of the overall
	// MARC record.
	size_t end_local_match(start_local_match + 2);
	while (end_local_match < fields.size()) {
	    const Subfields subfields2(fields[end_local_match]);
	    if (not subfields2.hasSubfield('0'))
		Error("weird data structure (2)!");
	    if (StringUtil::StartsWith(subfields2.getFirstSubfieldValue('0'), "000 "))
		break;

	    ++end_local_match;
	}

        for (ssize_t dir_entry_index(end_local_match - 1); dir_entry_index >= start_local_match; --dir_entry_index)
	    record->deleteField(dir_entry_index);

	modified = true;
    }

    return modified;
}

void ProcessRecords(const std::unordered_set <std::string> &title_deletion_ids,
                    const std::unordered_set <std::string> &local_deletion_ids, File *const input,
                    File *const output)
{
    unsigned total_record_count(0), deleted_record_count(0), modified_record_count(0);
    while (MarcUtil::Record record = MarcUtil::Record::XmlFactory(input)) {
        ++total_record_count;

	const std::vector<DirectoryEntry> &dir_entries(record.getDirEntries());
        if (dir_entries[0].getTag() != "001")
            Error("First field is not \"001\"!");

	const std::vector<std::string> &fields(record.getFields());
        if (title_deletion_ids.find(fields[0]) != title_deletion_ids.end()) {
            ++deleted_record_count;
            std::cout << "Deleted record with ID " << fields[0] << '\n';
        } else { // Look for local (LOK) data sets that may need to be deleted.
            if (not DeleteLocalSections(dir_entries, fields, local_deletion_ids, &record))
		record.write(output);
            else {
                // Only keep records that still have at least one "LOK" tag:
                if (std::find_if(dir_entries.cbegin(), dir_entries.cend(), MatchTag("LOK")) == dir_entries.cend())
                    ++deleted_record_count;
                else {
                    ++modified_record_count;
		    record.write(output);
                }
            }
        }
    }

    std::cerr << "Read " << total_record_count << " records.\n";
    std::cerr << "Deleted " << deleted_record_count << " records.\n";
    std::cerr << "Modified " << modified_record_count << " records.\n";
}

int main(int argc, char *argv[]) {
    progname = argv[0];

    if (argc != 4)
        Usage();

    const std::string deletion_list_filename(argv[1]);
    File deletion_list(deletion_list_filename, "rm");
    if (not deletion_list)
        Error("can't open \"" + deletion_list_filename + "\" for reading!");

    std::unordered_set <std::string> title_deletion_ids, local_deletion_ids;
    ExtractDeletionIds(&deletion_list, &title_deletion_ids, &local_deletion_ids);

    const std::string marc_input_filename(argv[2]);
    File marc_input(marc_input_filename, "rm");
    if (not marc_input)
        Error("can't open \"" + marc_input_filename + "\" for reading!");

    const std::string marc_output_filename(argv[3]);
    File marc_output(marc_output_filename, "w");
    if (not marc_output)
        Error("can't open \"" + marc_output_filename + "\" for writing!");

    try {
        ProcessRecords(title_deletion_ids, local_deletion_ids, &marc_input, &marc_output);
    } catch (const std::exception &e) {
        Error("Caught exception: " + std::string(e.what()));
    }
}
<commit_msg>Reverted the processing to MARC-21.<commit_after>/** \brief Utility for deleting partial or entire MARC records based on an input list.
 *  \author Dr. Johannes Ruscheinski (johannes.ruscheinski@uni-tuebingen.de)
 *
 *  \copyright 2015 Universitätsbiblothek Tübingen.  All rights reserved.
 *
 *  This program is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU Affero General Public License as
 *  published by the Free Software Foundation, either version 3 of the
 *  License, or (at your option) any later version.
 *
 *  This program 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 Affero General Public License for more details.
 *
 *  You should have received a copy of the GNU Affero General Public License
 *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/

#include <algorithm>
#include <iostream>
#include <memory>
#include <stdexcept>
#include <unordered_set>
#include <vector>
#include <cstdio>
#include <cstdlib>
#include "Compiler.h"
#include "MarcUtil.h"
#include "StringUtil.h"
#include "Subfields.h"
#include "util.h"

static void Usage() __attribute__((noreturn));

static void Usage() {
    std::cerr << "Usage: " << progname << " deletion_list input_marc output_marc\n";
    std::exit(EXIT_FAILURE);
}

void ExtractDeletionIds(File *const deletion_list, std::unordered_set <std::string> * const title_deletion_ids,
                        std::unordered_set <std::string> *const local_deletion_ids) {
    unsigned line_no(0);
    while (not deletion_list->eof()) {
	const std::string line(StringUtil::Trim(deletion_list->getline()));
        ++line_no;
	if (unlikely(line.empty())) // Ignore empty lines.
	    continue;
        if (line.length() < 12)
            Error("short line in deletion list file: \"" + line + "\"!");
        if (line[11] == 'A')
            title_deletion_ids->insert(line.substr(12)); // extract PPN
        else if (line[11] == '9') {
            if (line.length() != 25)
                Error("unexpected line length for local entry on line " + std::to_string(line_no) + "!");
            local_deletion_ids->insert(line.substr(12, 9)); // extract ELN
        }
    }
}

int MatchLocalID(const std::unordered_set <std::string> &local_ids, const std::vector <DirectoryEntry> &dir_entries,
                 const std::vector <std::string> &field_data) {
    for (size_t i(0); i < dir_entries.size(); ++i) {
        if (dir_entries[i].getTag() != "LOK")
            continue;

        const Subfields subfields(field_data[i]);
        if (not subfields.hasSubfield('0'))
            continue;

        const std::string subfield_contents(subfields.getFirstSubfieldValue('0'));
        if (not StringUtil::StartsWith(subfield_contents, "001 ")
            or local_ids.find(subfield_contents.substr(4)) == local_ids.end())
            continue;

        return i;
    }

    return -1;
}

class MatchTag {
    const std::string tag_to_match_;
public:
    explicit MatchTag(const std::string &tag_to_match) : tag_to_match_(tag_to_match) { }

    bool operator()(const DirectoryEntry &dir_entry) const { return dir_entry.getTag() == tag_to_match_; }
};

/** \brief Deletes LOK sections if their pseudo tags are found in "local_deletion_ids"
 *  \return True if at least one local section has been deleted, else false.
 */
bool DeleteLocalSections(const std::vector<DirectoryEntry> &dir_entries, const std::vector<std::string> &fields,
			 const std::unordered_set <std::string> &local_deletion_ids, MarcUtil::Record * const record)
{
    bool modified(false);

    ssize_t start_local_match;
    while ((start_local_match = MatchLocalID(local_deletion_ids, dir_entries, fields)) != -1) {
	// We now expect a field "000" before the current "001" field.  (This is just a sanity check!):
	--start_local_match;
	if (start_local_match <= 0)
	    Error("weird data structure (1)!");
	const Subfields subfields1(fields[start_local_match]);
	if (not subfields1.hasSubfield('0')
	    or not StringUtil::StartsWith(subfields1.getFirstSubfieldValue('0'), "000 "))
	    Error("missing or empty local field \"000\"! (EPN: "
		  + fields[start_local_match + 1].substr(8) + ", PPN: " + fields[0] + ")");

	// Now we need to find the index one past the end of the local record.  This would
	// be either the "000" field of the next local record or one past the end of the overall
	// MARC record.
	size_t end_local_match(start_local_match + 2);
	while (end_local_match < fields.size()) {
	    const Subfields subfields2(fields[end_local_match]);
	    if (not subfields2.hasSubfield('0'))
		Error("weird data structure (2)!");
	    if (StringUtil::StartsWith(subfields2.getFirstSubfieldValue('0'), "000 "))
		break;

	    ++end_local_match;
	}

        for (ssize_t dir_entry_index(end_local_match - 1); dir_entry_index >= start_local_match; --dir_entry_index)
	    record->deleteField(dir_entry_index);

	modified = true;
    }

    return modified;
}

void ProcessRecords(const std::unordered_set <std::string> &title_deletion_ids,
                    const std::unordered_set <std::string> &local_deletion_ids, File *const input,
                    File *const output)
{
    unsigned total_record_count(0), deleted_record_count(0), modified_record_count(0);
    while (MarcUtil::Record record = MarcUtil::Record::BinaryFactory(input)) {
        ++total_record_count;

	const std::vector<DirectoryEntry> &dir_entries(record.getDirEntries());
        if (dir_entries[0].getTag() != "001")
            Error("First field is not \"001\"!");

	const std::vector<std::string> &fields(record.getFields());
        if (title_deletion_ids.find(fields[0]) != title_deletion_ids.end()) {
            ++deleted_record_count;
            std::cout << "Deleted record with ID " << fields[0] << '\n';
        } else { // Look for local (LOK) data sets that may need to be deleted.
            if (not DeleteLocalSections(dir_entries, fields, local_deletion_ids, &record))
		record.write(output);
            else {
                // Only keep records that still have at least one "LOK" tag:
                if (std::find_if(dir_entries.cbegin(), dir_entries.cend(), MatchTag("LOK")) == dir_entries.cend())
                    ++deleted_record_count;
                else {
                    ++modified_record_count;
		    record.write(output);
                }
            }
        }
    }

    std::cerr << "Read " << total_record_count << " records.\n";
    std::cerr << "Deleted " << deleted_record_count << " records.\n";
    std::cerr << "Modified " << modified_record_count << " records.\n";
}

int main(int argc, char *argv[]) {
    progname = argv[0];

    if (argc != 4)
        Usage();

    const std::string deletion_list_filename(argv[1]);
    File deletion_list(deletion_list_filename, "rm");
    if (not deletion_list)
        Error("can't open \"" + deletion_list_filename + "\" for reading!");

    std::unordered_set <std::string> title_deletion_ids, local_deletion_ids;
    ExtractDeletionIds(&deletion_list, &title_deletion_ids, &local_deletion_ids);

    const std::string marc_input_filename(argv[2]);
    File marc_input(marc_input_filename, "rm");
    if (not marc_input)
        Error("can't open \"" + marc_input_filename + "\" for reading!");

    const std::string marc_output_filename(argv[3]);
    File marc_output(marc_output_filename, "w");
    if (not marc_output)
        Error("can't open \"" + marc_output_filename + "\" for writing!");

    try {
        ProcessRecords(title_deletion_ids, local_deletion_ids, &marc_input, &marc_output);
    } catch (const std::exception &e) {
        Error("Caught exception: " + std::string(e.what()));
    }
}
<|endoftext|>


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

#include "content/renderer/gpu/gpu_video_decode_accelerator_host.h"

#include "base/bind.h"
#include "base/logging.h"
#include "base/message_loop.h"
#include "base/task.h"
#include "content/common/gpu/gpu_messages.h"
#include "content/common/view_messages.h"
#include "content/renderer/render_thread.h"
#include "ipc/ipc_message_macros.h"
#include "ipc/ipc_message_utils.h"

using media::VideoDecodeAccelerator;

GpuVideoDecodeAcceleratorHost::GpuVideoDecodeAcceleratorHost(
    IPC::Message::Sender* ipc_sender,
    int32 command_buffer_route_id,
    VideoDecodeAccelerator::Client* client)
    : ipc_sender_(ipc_sender),
      command_buffer_route_id_(command_buffer_route_id),
      client_(client) {
  DCHECK(ipc_sender_);
  DCHECK(client_);
  DCHECK(RenderThread::current());
  DCHECK_EQ(RenderThread::current()->message_loop(), MessageLoop::current());
}

GpuVideoDecodeAcceleratorHost::~GpuVideoDecodeAcceleratorHost() {}

void GpuVideoDecodeAcceleratorHost::OnChannelError() {
  ipc_sender_ = NULL;
}

bool GpuVideoDecodeAcceleratorHost::OnMessageReceived(const IPC::Message& msg) {
  DCHECK(CalledOnValidThread());
  bool handled = true;
  IPC_BEGIN_MESSAGE_MAP(GpuVideoDecodeAcceleratorHost, msg)
    IPC_MESSAGE_HANDLER(AcceleratedVideoDecoderHostMsg_BitstreamBufferProcessed,
                        OnBitstreamBufferProcessed)
    IPC_MESSAGE_HANDLER(AcceleratedVideoDecoderHostMsg_ProvidePictureBuffers,
                        OnProvidePictureBuffer)
    IPC_MESSAGE_HANDLER(AcceleratedVideoDecoderHostMsg_PictureReady,
                        OnPictureReady)
    IPC_MESSAGE_HANDLER(AcceleratedVideoDecoderHostMsg_FlushDone,
                        OnFlushDone)
    IPC_MESSAGE_HANDLER(AcceleratedVideoDecoderHostMsg_ResetDone,
                        OnResetDone)
    IPC_MESSAGE_HANDLER(AcceleratedVideoDecoderHostMsg_EndOfStream,
                        OnEndOfStream)
    IPC_MESSAGE_HANDLER(AcceleratedVideoDecoderHostMsg_ErrorNotification,
                        OnErrorNotification)
    IPC_MESSAGE_UNHANDLED(handled = false)
  IPC_END_MESSAGE_MAP()
  DCHECK(handled);
  return handled;
}

bool GpuVideoDecodeAcceleratorHost::Initialize(
    const std::vector<int32>& configs) {
  NOTREACHED();
  return true;
}

void GpuVideoDecodeAcceleratorHost::Decode(
    const media::BitstreamBuffer& bitstream_buffer) {
  DCHECK(CalledOnValidThread());
  Send(new AcceleratedVideoDecoderMsg_Decode(
      command_buffer_route_id_, bitstream_buffer.handle(),
      bitstream_buffer.id(), bitstream_buffer.size()));
}

void GpuVideoDecodeAcceleratorHost::AssignPictureBuffers(
    const std::vector<media::PictureBuffer>& buffers) {
  DCHECK(CalledOnValidThread());
  // Rearrange data for IPC command.
  std::vector<int32> buffer_ids;
  std::vector<uint32> texture_ids;
  std::vector<gfx::Size> sizes;
  for (uint32 i = 0; i < buffers.size(); i++) {
    const media::PictureBuffer& buffer = buffers[i];
    texture_ids.push_back(buffer.texture_id());
    buffer_ids.push_back(buffer.id());
    sizes.push_back(buffer.size());
  }
  Send(new AcceleratedVideoDecoderMsg_AssignPictureBuffers(
      command_buffer_route_id_, buffer_ids, texture_ids, sizes));
}

void GpuVideoDecodeAcceleratorHost::ReusePictureBuffer(
    int32 picture_buffer_id) {
  DCHECK(CalledOnValidThread());
  Send(new AcceleratedVideoDecoderMsg_ReusePictureBuffer(
      command_buffer_route_id_, picture_buffer_id));
}

void GpuVideoDecodeAcceleratorHost::Flush() {
  DCHECK(CalledOnValidThread());
  Send(new AcceleratedVideoDecoderMsg_Flush(command_buffer_route_id_));
}

void GpuVideoDecodeAcceleratorHost::Reset() {
  DCHECK(CalledOnValidThread());
  Send(new AcceleratedVideoDecoderMsg_Reset(command_buffer_route_id_));
}

void GpuVideoDecodeAcceleratorHost::Destroy() {
  DCHECK(CalledOnValidThread());
  Send(new AcceleratedVideoDecoderMsg_Destroy(command_buffer_route_id_));
}

void GpuVideoDecodeAcceleratorHost::Send(IPC::Message* message) {
  // After OnChannelError is called, the client should no longer send
  // messages to the gpu channel through this object.
  DCHECK(ipc_sender_);
  if (!ipc_sender_ || !ipc_sender_->Send(message)) {
    DLOG(ERROR) << "Send(" << message->type() << ") failed";
    OnErrorNotification(PLATFORM_FAILURE);
  }
}

void GpuVideoDecodeAcceleratorHost::OnBitstreamBufferProcessed(
    int32 bitstream_buffer_id) {
  DCHECK(CalledOnValidThread());
  client_->NotifyEndOfBitstreamBuffer(bitstream_buffer_id);
}

void GpuVideoDecodeAcceleratorHost::OnProvidePictureBuffer(
    uint32 num_requested_buffers,
    const gfx::Size& buffer_size) {
  DCHECK(CalledOnValidThread());
  client_->ProvidePictureBuffers(num_requested_buffers, buffer_size);
}

void GpuVideoDecodeAcceleratorHost::OnDismissPictureBuffer(
    int32 picture_buffer_id) {
  DCHECK(CalledOnValidThread());
  client_->DismissPictureBuffer(picture_buffer_id);
}

void GpuVideoDecodeAcceleratorHost::OnPictureReady(
    int32 picture_buffer_id, int32 bitstream_buffer_id) {
  DCHECK(CalledOnValidThread());
  media::Picture picture(picture_buffer_id, bitstream_buffer_id);
  client_->PictureReady(picture);
}

void GpuVideoDecodeAcceleratorHost::OnFlushDone() {
  DCHECK(CalledOnValidThread());
  client_->NotifyFlushDone();
}

void GpuVideoDecodeAcceleratorHost::OnResetDone() {
  DCHECK(CalledOnValidThread());
  client_->NotifyResetDone();
}

void GpuVideoDecodeAcceleratorHost::OnEndOfStream() {
  DCHECK(CalledOnValidThread());
  client_->NotifyEndOfStream();
}

void GpuVideoDecodeAcceleratorHost::OnErrorNotification(uint32 error) {
  DCHECK(CalledOnValidThread());
  client_->NotifyError(
      static_cast<media::VideoDecodeAccelerator::Error>(error));
}
<commit_msg>Handle client going away after GVDAH::Destroy<commit_after>// Copyright (c) 2011 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "content/renderer/gpu/gpu_video_decode_accelerator_host.h"

#include "base/bind.h"
#include "base/logging.h"
#include "base/message_loop.h"
#include "base/task.h"
#include "content/common/gpu/gpu_messages.h"
#include "content/common/view_messages.h"
#include "content/renderer/render_thread.h"
#include "ipc/ipc_message_macros.h"
#include "ipc/ipc_message_utils.h"

using media::VideoDecodeAccelerator;

GpuVideoDecodeAcceleratorHost::GpuVideoDecodeAcceleratorHost(
    IPC::Message::Sender* ipc_sender,
    int32 command_buffer_route_id,
    VideoDecodeAccelerator::Client* client)
    : ipc_sender_(ipc_sender),
      command_buffer_route_id_(command_buffer_route_id),
      client_(client) {
  DCHECK(ipc_sender_);
  DCHECK(client_);
  DCHECK(RenderThread::current());
  DCHECK_EQ(RenderThread::current()->message_loop(), MessageLoop::current());
}

GpuVideoDecodeAcceleratorHost::~GpuVideoDecodeAcceleratorHost() {}

void GpuVideoDecodeAcceleratorHost::OnChannelError() {
  ipc_sender_ = NULL;
}

bool GpuVideoDecodeAcceleratorHost::OnMessageReceived(const IPC::Message& msg) {
  DCHECK(CalledOnValidThread());
  bool handled = true;
  IPC_BEGIN_MESSAGE_MAP(GpuVideoDecodeAcceleratorHost, msg)
    IPC_MESSAGE_HANDLER(AcceleratedVideoDecoderHostMsg_BitstreamBufferProcessed,
                        OnBitstreamBufferProcessed)
    IPC_MESSAGE_HANDLER(AcceleratedVideoDecoderHostMsg_ProvidePictureBuffers,
                        OnProvidePictureBuffer)
    IPC_MESSAGE_HANDLER(AcceleratedVideoDecoderHostMsg_PictureReady,
                        OnPictureReady)
    IPC_MESSAGE_HANDLER(AcceleratedVideoDecoderHostMsg_FlushDone,
                        OnFlushDone)
    IPC_MESSAGE_HANDLER(AcceleratedVideoDecoderHostMsg_ResetDone,
                        OnResetDone)
    IPC_MESSAGE_HANDLER(AcceleratedVideoDecoderHostMsg_EndOfStream,
                        OnEndOfStream)
    IPC_MESSAGE_HANDLER(AcceleratedVideoDecoderHostMsg_ErrorNotification,
                        OnErrorNotification)
    IPC_MESSAGE_UNHANDLED(handled = false)
  IPC_END_MESSAGE_MAP()
  DCHECK(handled);
  return handled;
}

bool GpuVideoDecodeAcceleratorHost::Initialize(
    const std::vector<int32>& configs) {
  NOTREACHED();
  return true;
}

void GpuVideoDecodeAcceleratorHost::Decode(
    const media::BitstreamBuffer& bitstream_buffer) {
  DCHECK(CalledOnValidThread());
  Send(new AcceleratedVideoDecoderMsg_Decode(
      command_buffer_route_id_, bitstream_buffer.handle(),
      bitstream_buffer.id(), bitstream_buffer.size()));
}

void GpuVideoDecodeAcceleratorHost::AssignPictureBuffers(
    const std::vector<media::PictureBuffer>& buffers) {
  DCHECK(CalledOnValidThread());
  // Rearrange data for IPC command.
  std::vector<int32> buffer_ids;
  std::vector<uint32> texture_ids;
  std::vector<gfx::Size> sizes;
  for (uint32 i = 0; i < buffers.size(); i++) {
    const media::PictureBuffer& buffer = buffers[i];
    texture_ids.push_back(buffer.texture_id());
    buffer_ids.push_back(buffer.id());
    sizes.push_back(buffer.size());
  }
  Send(new AcceleratedVideoDecoderMsg_AssignPictureBuffers(
      command_buffer_route_id_, buffer_ids, texture_ids, sizes));
}

void GpuVideoDecodeAcceleratorHost::ReusePictureBuffer(
    int32 picture_buffer_id) {
  DCHECK(CalledOnValidThread());
  Send(new AcceleratedVideoDecoderMsg_ReusePictureBuffer(
      command_buffer_route_id_, picture_buffer_id));
}

void GpuVideoDecodeAcceleratorHost::Flush() {
  DCHECK(CalledOnValidThread());
  Send(new AcceleratedVideoDecoderMsg_Flush(command_buffer_route_id_));
}

void GpuVideoDecodeAcceleratorHost::Reset() {
  DCHECK(CalledOnValidThread());
  Send(new AcceleratedVideoDecoderMsg_Reset(command_buffer_route_id_));
}

void GpuVideoDecodeAcceleratorHost::Destroy() {
  DCHECK(CalledOnValidThread());
  Send(new AcceleratedVideoDecoderMsg_Destroy(command_buffer_route_id_));
  client_ = NULL;
}

void GpuVideoDecodeAcceleratorHost::Send(IPC::Message* message) {
  // After OnChannelError is called, the client should no longer send
  // messages to the gpu channel through this object.
  DCHECK(ipc_sender_);
  if (!ipc_sender_ || !ipc_sender_->Send(message)) {
    DLOG(ERROR) << "Send(" << message->type() << ") failed";
    OnErrorNotification(PLATFORM_FAILURE);
  }
}

void GpuVideoDecodeAcceleratorHost::OnBitstreamBufferProcessed(
    int32 bitstream_buffer_id) {
  DCHECK(CalledOnValidThread());
  if (client_)
    client_->NotifyEndOfBitstreamBuffer(bitstream_buffer_id);
}

void GpuVideoDecodeAcceleratorHost::OnProvidePictureBuffer(
    uint32 num_requested_buffers,
    const gfx::Size& buffer_size) {
  DCHECK(CalledOnValidThread());
  if (client_)
    client_->ProvidePictureBuffers(num_requested_buffers, buffer_size);
}

void GpuVideoDecodeAcceleratorHost::OnDismissPictureBuffer(
    int32 picture_buffer_id) {
  DCHECK(CalledOnValidThread());
  if (client_)
    client_->DismissPictureBuffer(picture_buffer_id);
}

void GpuVideoDecodeAcceleratorHost::OnPictureReady(
    int32 picture_buffer_id, int32 bitstream_buffer_id) {
  DCHECK(CalledOnValidThread());
  if (!client_)
    return;
  media::Picture picture(picture_buffer_id, bitstream_buffer_id);
  client_->PictureReady(picture);
}

void GpuVideoDecodeAcceleratorHost::OnFlushDone() {
  DCHECK(CalledOnValidThread());
  if (client_)
    client_->NotifyFlushDone();
}

void GpuVideoDecodeAcceleratorHost::OnResetDone() {
  DCHECK(CalledOnValidThread());
  if (client_)
    client_->NotifyResetDone();
}

void GpuVideoDecodeAcceleratorHost::OnEndOfStream() {
  DCHECK(CalledOnValidThread());
  if (client_)
    client_->NotifyEndOfStream();
}

void GpuVideoDecodeAcceleratorHost::OnErrorNotification(uint32 error) {
  DCHECK(CalledOnValidThread());
  if (!client_)
    return;
  client_->NotifyError(
      static_cast<media::VideoDecodeAccelerator::Error>(error));
}
<|endoftext|>


<commit_before>/*
 * Search.cpp
 *
 *  Created on: 16 Nov 2015
 *      Author: hieu
 */
#include <boost/foreach.hpp>
#include "Search.h"
#include "../Manager.h"
#include "../Hypothesis.h"
#include "../../InputPaths.h"
#include "../../InputPath.h"
#include "../../System.h"
#include "../../TranslationTask.h"
#include "../../legacy/Util2.h"

using namespace std;

namespace NSCubePruning
{

////////////////////////////////////////////////////////////////////////
Search::Search(Manager &mgr)
: ::Search(mgr)
{
}

Search::~Search() {
}

void Search::Decode()
{
	// init stacks
	m_stacks.Init(m_mgr.GetInput().GetSize() + 1);
	m_cubeEdges.resize(m_stacks.GetSize() + 1);

	const Bitmap &initBitmap = m_mgr.GetBitmaps().GetInitialBitmap();
	Hypothesis *initHypo = Hypothesis::Create(m_mgr);
	initHypo->Init(m_mgr.GetInitPhrase(), m_mgr.GetInitRange(), initBitmap);
	initHypo->EmptyHypothesisState(m_mgr.GetInput());

	m_stacks.Add(initHypo, m_mgr.GetHypoRecycle());

	for (size_t stackInd = 0; stackInd < m_stacks.GetSize(); ++stackInd) {
		//cerr << "stackInd=" << stackInd << endl;
		Decode(stackInd);
		PostDecode(stackInd);

		//cerr << m_stacks << endl;

		// delete stack to save mem
		if (stackInd < m_stacks.GetSize() - 1) {
			//m_stacks.Delete(stackInd);
		}
		//cerr << m_stacks << endl;
	}

}

// grab the underlying contain of priority queue
/////////////////////////////////////////////////
template <class T, class S, class C>
    S& Container(priority_queue<T, S, C>& q) {
        struct HackedQueue : private priority_queue<T, S, C> {
            static S& Container(priority_queue<T, S, C>& q) {
                return q.*&HackedQueue::c;
            }
        };
    return HackedQueue::Container(q);
}
/////////////////////////////////////////////////

void Search::Decode(size_t stackInd)
{
	std::vector<QueueItem*> &queueContainer = Container(m_queue);
	queueContainer.clear();

	m_seenPositions.clear();

	// add top hypo from every edge into queue
	CubeEdges &edges = m_cubeEdges[stackInd];

	BOOST_FOREACH(CubeEdge *edge, edges) {
		//cerr << "edge=" << *edge << endl;
		edge->CreateFirst(m_mgr, m_queue, m_seenPositions);
	}

	/*
	cerr << "queue:" << endl;
	vector<QueueItem*> &queueContainer = Container(queue);
	for (size_t i = 0; i < queueContainer.size(); ++i) {
		QueueItem *item = queueContainer[i];
		Hypothesis *hypo = item->hypo;
		cerr << *hypo << endl;
	}
	cerr << endl;
	*/

	size_t pops = 0;
	while (!m_queue.empty() && pops < m_mgr.system.popLimit) {
		// get best hypo from queue, add to stack
		//cerr << "queue=" << queue.size() << endl;
		QueueItem *item = m_queue.top();
		m_queue.pop();

		Hypothesis *hypo = item->hypo;
		//cerr << "hypo=" << *hypo << " " << hypo->GetBitmap() << endl;
		m_stacks.Add(hypo, m_mgr.GetHypoRecycle());

		CubeEdge &edge = item->edge;
		edge.CreateNext(m_mgr, item, m_queue, m_seenPositions);

		m_mgr.task.poolQueueItem.free(item);

		++pops;
	}

	//m_mgr.task.poolQueueItem;

	BOOST_FOREACH(CubeEdge *edge, edges) {
		//cerr << "edge=" << *edge << endl;
		m_mgr.task.poolCubeEdge.free(edge);
	}
}

void Search::PostDecode(size_t stackInd)
{
  Stack &stack = m_stacks[stackInd];
  MemPool &pool = m_mgr.GetPool();

  BOOST_FOREACH(const Stack::Coll::value_type &val, stack.GetColl()) {
	  const Bitmap &hypoBitmap = *val.first.first;
	  size_t hypoEndPos = val.first.second;
	  //cerr << "key=" << hypoBitmap << " " << hypoEndPos << endl;

	  // create edges to next hypos from existing hypos
	  const InputPaths &paths = m_mgr.GetInputPaths();

	  BOOST_FOREACH(const InputPath &path, paths) {
  		const Range &pathRange = path.range;
  		//cerr << "pathRange=" << pathRange << endl;

  		if (!path.IsUsed()) {
  			continue;
  		}
  		if (!CanExtend(hypoBitmap, hypoEndPos, pathRange)) {
  			continue;
  		}

  		const Bitmap &newBitmap = m_mgr.GetBitmaps().GetBitmap(hypoBitmap, pathRange);
  		size_t numWords = newBitmap.GetNumWordsCovered();

  		CubeEdges &edges = m_cubeEdges[numWords];

		// sort hypo for a particular bitmap and hypoEndPos
		CubeEdge::Hypotheses &sortedHypos = val.second.GetSortedHypos(m_mgr);

  		BOOST_FOREACH(const TargetPhrases::shared_const_ptr &tpsPtr, path.targetPhrases) {
  			const TargetPhrases *tps = tpsPtr.get();
  			if (tps && tps->GetSize()) {
  		  		CubeEdge *edge = new (m_mgr.task.poolCubeEdge.malloc()) CubeEdge(m_mgr, sortedHypos, path, *tps, newBitmap);
  		  		edges.push_back(edge);
  			}
  		}
  	  }
  }
}

const Hypothesis *Search::GetBestHypothesis() const
{
	const Stack &lastStack = m_stacks.Back();
	std::vector<const Hypothesis*> sortedHypos = lastStack.GetBestHypos(1);

	const Hypothesis *best = NULL;
	if (sortedHypos.size()) {
		best = sortedHypos[0];
	}
	return best;
}

}

<commit_msg>clear queue<commit_after>/*
 * Search.cpp
 *
 *  Created on: 16 Nov 2015
 *      Author: hieu
 */
#include <boost/foreach.hpp>
#include "Search.h"
#include "../Manager.h"
#include "../Hypothesis.h"
#include "../../InputPaths.h"
#include "../../InputPath.h"
#include "../../System.h"
#include "../../TranslationTask.h"
#include "../../legacy/Util2.h"

using namespace std;

namespace NSCubePruning
{

////////////////////////////////////////////////////////////////////////
Search::Search(Manager &mgr)
: ::Search(mgr)
{
}

Search::~Search() {
}

void Search::Decode()
{
	// init stacks
	m_stacks.Init(m_mgr.GetInput().GetSize() + 1);
	m_cubeEdges.resize(m_stacks.GetSize() + 1);

	const Bitmap &initBitmap = m_mgr.GetBitmaps().GetInitialBitmap();
	Hypothesis *initHypo = Hypothesis::Create(m_mgr);
	initHypo->Init(m_mgr.GetInitPhrase(), m_mgr.GetInitRange(), initBitmap);
	initHypo->EmptyHypothesisState(m_mgr.GetInput());

	m_stacks.Add(initHypo, m_mgr.GetHypoRecycle());

	for (size_t stackInd = 0; stackInd < m_stacks.GetSize(); ++stackInd) {
		//cerr << "stackInd=" << stackInd << endl;
		Decode(stackInd);
		PostDecode(stackInd);

		//cerr << m_stacks << endl;

		// delete stack to save mem
		if (stackInd < m_stacks.GetSize() - 1) {
			//m_stacks.Delete(stackInd);
		}
		//cerr << m_stacks << endl;
	}

}

// grab the underlying contain of priority queue
/////////////////////////////////////////////////
template <class T, class S, class C>
    S& Container(priority_queue<T, S, C>& q) {
        struct HackedQueue : private priority_queue<T, S, C> {
            static S& Container(priority_queue<T, S, C>& q) {
                return q.*&HackedQueue::c;
            }
        };
    return HackedQueue::Container(q);
}
/////////////////////////////////////////////////

void Search::Decode(size_t stackInd)
{
	std::vector<QueueItem*> &queueContainer = Container(m_queue);
	queueContainer.clear();

	m_seenPositions.clear();

	// add top hypo from every edge into queue
	CubeEdges &edges = m_cubeEdges[stackInd];

	BOOST_FOREACH(CubeEdge *edge, edges) {
		//cerr << "edge=" << *edge << endl;
		edge->CreateFirst(m_mgr, m_queue, m_seenPositions);
	}

	/*
	cerr << "queue:" << endl;
	vector<QueueItem*> &queueContainer = Container(queue);
	for (size_t i = 0; i < queueContainer.size(); ++i) {
		QueueItem *item = queueContainer[i];
		Hypothesis *hypo = item->hypo;
		cerr << *hypo << endl;
	}
	cerr << endl;
	*/

	size_t pops = 0;
	while (!m_queue.empty() && pops < m_mgr.system.popLimit) {
		// get best hypo from queue, add to stack
		//cerr << "queue=" << queue.size() << endl;
		QueueItem *item = m_queue.top();
		m_queue.pop();

		Hypothesis *hypo = item->hypo;
		//cerr << "hypo=" << *hypo << " " << hypo->GetBitmap() << endl;
		m_stacks.Add(hypo, m_mgr.GetHypoRecycle());

		CubeEdge &edge = item->edge;
		edge.CreateNext(m_mgr, item, m_queue, m_seenPositions);

		m_mgr.task.poolQueueItem.free(item);

		++pops;
	}

	// clear queue
	while (!m_queue.empty()) {
		QueueItem *item = m_queue.top();
		m_queue.pop();

		m_mgr.task.poolQueueItem.free(item);
	}

	BOOST_FOREACH(CubeEdge *edge, edges) {
		//cerr << "edge=" << *edge << endl;
		m_mgr.task.poolCubeEdge.free(edge);
	}
}

void Search::PostDecode(size_t stackInd)
{
  Stack &stack = m_stacks[stackInd];
  MemPool &pool = m_mgr.GetPool();

  BOOST_FOREACH(const Stack::Coll::value_type &val, stack.GetColl()) {
	  const Bitmap &hypoBitmap = *val.first.first;
	  size_t hypoEndPos = val.first.second;
	  //cerr << "key=" << hypoBitmap << " " << hypoEndPos << endl;

	  // create edges to next hypos from existing hypos
	  const InputPaths &paths = m_mgr.GetInputPaths();

	  BOOST_FOREACH(const InputPath &path, paths) {
  		const Range &pathRange = path.range;
  		//cerr << "pathRange=" << pathRange << endl;

  		if (!path.IsUsed()) {
  			continue;
  		}
  		if (!CanExtend(hypoBitmap, hypoEndPos, pathRange)) {
  			continue;
  		}

  		const Bitmap &newBitmap = m_mgr.GetBitmaps().GetBitmap(hypoBitmap, pathRange);
  		size_t numWords = newBitmap.GetNumWordsCovered();

  		CubeEdges &edges = m_cubeEdges[numWords];

		// sort hypo for a particular bitmap and hypoEndPos
		CubeEdge::Hypotheses &sortedHypos = val.second.GetSortedHypos(m_mgr);

  		BOOST_FOREACH(const TargetPhrases::shared_const_ptr &tpsPtr, path.targetPhrases) {
  			const TargetPhrases *tps = tpsPtr.get();
  			if (tps && tps->GetSize()) {
  		  		CubeEdge *edge = new (m_mgr.task.poolCubeEdge.malloc()) CubeEdge(m_mgr, sortedHypos, path, *tps, newBitmap);
  		  		edges.push_back(edge);
  			}
  		}
  	  }
  }
}

const Hypothesis *Search::GetBestHypothesis() const
{
	const Stack &lastStack = m_stacks.Back();
	std::vector<const Hypothesis*> sortedHypos = lastStack.GetBestHypos(1);

	const Hypothesis *best = NULL;
	if (sortedHypos.size()) {
		best = sortedHypos[0];
	}
	return best;
}

}

<|endoftext|>


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

#include "chrome/browser/views/bug_report_view.h"

#include "app/combobox_model.h"
#include "app/l10n_util.h"
#include "app/win_util.h"
#include "base/file_version_info.h"
#include "base/string_util.h"
#include "chrome/browser/bug_report_util.h"
#include "chrome/browser/net/url_fetcher.h"
#include "chrome/browser/profile.h"
#include "chrome/browser/safe_browsing/safe_browsing_util.h"
#include "chrome/browser/tab_contents/navigation_controller.h"
#include "chrome/browser/tab_contents/navigation_entry.h"
#include "chrome/browser/tab_contents/tab_contents.h"
#include "chrome/common/pref_names.h"
#include "chrome/common/pref_service.h"
#include "grit/chromium_strings.h"
#include "grit/generated_resources.h"
#include "grit/locale_settings.h"
#include "net/base/escape.h"
#include "unicode/locid.h"
#include "views/controls/button/checkbox.h"
#include "views/controls/label.h"
#include "views/grid_layout.h"
#include "views/standard_layout.h"
#include "views/widget/widget.h"
#include "views/window/client_view.h"
#include "views/window/window.h"

using views::ColumnSet;
using views::GridLayout;

// Report a bug data version.
static const int kBugReportVersion = 1;

// Number of lines description field can display at one time.
static const int kDescriptionLines = 5;

class BugReportComboBoxModel : public ComboboxModel {
 public:
  BugReportComboBoxModel() {}

  enum BugType {
    PAGE_WONT_LOAD = 0,
    PAGE_LOOKS_ODD,
    PHISHING_PAGE,
    CANT_SIGN_IN,
    CHROME_MISBEHAVES,
    SOMETHING_MISSING,
    BROWSER_CRASH,
    OTHER_PROBLEM
  };

  // ComboboxModel interface.
  virtual int GetItemCount() {
    return OTHER_PROBLEM + 1;
  }

  virtual std::wstring GetItemAt(int index) {
    return GetItemAtIndex(index);
  }

  static std::wstring GetItemAtIndex(int index) {
    switch (index) {
      case PAGE_WONT_LOAD:
        return l10n_util::GetString(IDS_BUGREPORT_PAGE_WONT_LOAD);
      case PAGE_LOOKS_ODD:
        return l10n_util::GetString(IDS_BUGREPORT_PAGE_LOOKS_ODD);
      case PHISHING_PAGE:
        return l10n_util::GetString(IDS_BUGREPORT_PHISHING_PAGE);
      case CANT_SIGN_IN:
        return l10n_util::GetString(IDS_BUGREPORT_CANT_SIGN_IN);
      case CHROME_MISBEHAVES:
        return l10n_util::GetString(IDS_BUGREPORT_CHROME_MISBEHAVES);
      case SOMETHING_MISSING:
        return l10n_util::GetString(IDS_BUGREPORT_SOMETHING_MISSING);
      case BROWSER_CRASH:
        return l10n_util::GetString(IDS_BUGREPORT_BROWSER_CRASH);
      case OTHER_PROBLEM:
        return l10n_util::GetString(IDS_BUGREPORT_OTHER_PROBLEM);
      default:
        NOTREACHED();
        return std::wstring();
    }
  }

 private:
  DISALLOW_COPY_AND_ASSIGN(BugReportComboBoxModel);
};

namespace browser {

// Global "display this dialog" function declared in browser_dialogs.h.
void ShowBugReportView(views::Widget* parent,
                       Profile* profile,
                       TabContents* tab) {
  BugReportView* view = new BugReportView(profile, tab);

  // Grab an exact snapshot of the window that the user is seeing (i.e. as
  // rendered--do not re-render, and include windowed plugins).
  std::vector<unsigned char> *screenshot_png = new std::vector<unsigned char>;
  win_util::GrabWindowSnapshot(parent->GetNativeView(), screenshot_png);
  // The BugReportView takes ownership of the png data, and will dispose of
  // it in its destructor.
  view->set_png_data(screenshot_png);

  // Create and show the dialog.
  views::Window::CreateChromeWindow(parent->GetNativeView(), gfx::Rect(),
                                    view)->Show();
}

}  // namespace browser

// BugReportView - create and submit a bug report from the user.
// This is separate from crash reporting, which is handled by Breakpad.
//
BugReportView::BugReportView(Profile* profile, TabContents* tab)
    : include_page_source_checkbox_(NULL),
      include_page_image_checkbox_(NULL),
      profile_(profile),
      tab_(tab),
      problem_type_(0) {
  DCHECK(profile);
  SetupControl();

  // We want to use the URL of the current committed entry (the current URL may
  // actually be the pending one).
  if (tab->controller().GetActiveEntry()) {
    page_url_text_->SetText(UTF8ToWide(
        tab->controller().GetActiveEntry()->url().spec()));
  }

  // Retrieve the application version info.
  scoped_ptr<FileVersionInfo> version_info(
      FileVersionInfo::CreateFileVersionInfoForCurrentModule());
  if (version_info.get()) {
    version_ = version_info->product_name() + L" - " +
        version_info->file_version() +
        L" (" + version_info->last_change() + L")";
  }
}

BugReportView::~BugReportView() {
}

void BugReportView::SetupControl() {
  bug_type_model_.reset(new BugReportComboBoxModel);

  // Adds all controls.
  bug_type_label_ = new views::Label(
      l10n_util::GetString(IDS_BUGREPORT_BUG_TYPE));
  bug_type_combo_ = new views::Combobox(bug_type_model_.get());
  bug_type_combo_->set_listener(this);

  page_title_label_ = new views::Label(
      l10n_util::GetString(IDS_BUGREPORT_REPORT_PAGE_TITLE));
  page_title_text_ = new views::Label(UTF16ToWideHack(tab_->GetTitle()));
  page_url_label_ = new views::Label(
      l10n_util::GetString(IDS_BUGREPORT_REPORT_URL_LABEL));
  // page_url_text_'s text (if any) is filled in after dialog creation.
  page_url_text_ = new views::Textfield;
  page_url_text_->SetController(this);

  description_label_ = new views::Label(
      l10n_util::GetString(IDS_BUGREPORT_DESCRIPTION_LABEL));
  description_text_ =
      new views::Textfield(views::Textfield::STYLE_MULTILINE);
  description_text_->SetHeightInLines(kDescriptionLines);

  include_page_source_checkbox_ = new views::Checkbox(
      l10n_util::GetString(IDS_BUGREPORT_INCLUDE_PAGE_SOURCE_CHKBOX));
  include_page_source_checkbox_->SetChecked(true);
  include_page_image_checkbox_ = new views::Checkbox(
      l10n_util::GetString(IDS_BUGREPORT_INCLUDE_PAGE_IMAGE_CHKBOX));
  include_page_image_checkbox_->SetChecked(true);

  // Arranges controls by using GridLayout.
  const int column_set_id = 0;
  GridLayout* layout = CreatePanelGridLayout(this);
  SetLayoutManager(layout);
  ColumnSet* column_set = layout->AddColumnSet(column_set_id);
  column_set->AddColumn(GridLayout::LEADING, GridLayout::FILL, 0,
                        GridLayout::USE_PREF, 0, 0);
  column_set->AddPaddingColumn(0, kRelatedControlHorizontalSpacing * 2);
  column_set->AddColumn(GridLayout::FILL, GridLayout::FILL, 1,
                        GridLayout::USE_PREF, 0, 0);

  // Page Title and text.
  layout->StartRow(0, column_set_id);
  layout->AddView(page_title_label_);
  layout->AddView(page_title_text_, 1, 1, GridLayout::LEADING,
                  GridLayout::FILL);
  layout->AddPaddingRow(0, kRelatedControlVerticalSpacing);

  // Bug type and combo box.
  layout->StartRow(0, column_set_id);
  layout->AddView(bug_type_label_, 1, 1, GridLayout::LEADING, GridLayout::FILL);
  layout->AddView(bug_type_combo_);
  layout->AddPaddingRow(0, kRelatedControlVerticalSpacing);

  // Page URL and text field.
  layout->StartRow(0, column_set_id);
  layout->AddView(page_url_label_);
  layout->AddView(page_url_text_);
  layout->AddPaddingRow(0, kRelatedControlVerticalSpacing);

  // Description label and text field.
  layout->StartRow(0, column_set_id);
  layout->AddView(description_label_, 1, 1, GridLayout::LEADING,
                  GridLayout::LEADING);
  layout->AddView(description_text_, 1, 1, GridLayout::FILL,
                  GridLayout::LEADING);
  layout->AddPaddingRow(0, kUnrelatedControlVerticalSpacing);

  // Checkboxes.
  // The include page source checkbox is hidden until we can make it work.
  // layout->StartRow(0, column_set_id);
  // layout->SkipColumns(1);
  // layout->AddView(include_page_source_checkbox_);
  // layout->AddPaddingRow(0, kRelatedControlVerticalSpacing);
  layout->StartRow(0, column_set_id);
  layout->SkipColumns(1);
  layout->AddView(include_page_image_checkbox_);
  layout->AddPaddingRow(0, kUnrelatedControlVerticalSpacing);
}

gfx::Size BugReportView::GetPreferredSize() {
  return gfx::Size(views::Window::GetLocalizedContentsSize(
      IDS_BUGREPORT_DIALOG_WIDTH_CHARS,
      IDS_BUGREPORT_DIALOG_HEIGHT_LINES));
}

void BugReportView::ItemChanged(views::Combobox* combobox,
                                int prev_index,
                                int new_index) {
  if (new_index == prev_index)
    return;

  problem_type_ = new_index;
  bool is_phishing_report = new_index == BugReportComboBoxModel::PHISHING_PAGE;

  description_text_->SetEnabled(!is_phishing_report);
  description_text_->SetReadOnly(is_phishing_report);
  if (is_phishing_report) {
    old_report_text_ = description_text_->text();
    description_text_->SetText(std::wstring());
  } else if (!old_report_text_.empty()) {
    description_text_->SetText(old_report_text_);
    old_report_text_.clear();
  }
  include_page_source_checkbox_->SetEnabled(!is_phishing_report);
  include_page_source_checkbox_->SetChecked(!is_phishing_report);
  include_page_image_checkbox_->SetEnabled(!is_phishing_report);
  include_page_image_checkbox_->SetChecked(!is_phishing_report);

  GetDialogClientView()->UpdateDialogButtons();
}

void BugReportView::ContentsChanged(views::Textfield* sender,
                                    const std::wstring& new_contents) {
}

bool BugReportView::HandleKeystroke(views::Textfield* sender,
                                    const views::Textfield::Keystroke& key) {
  return false;
}

std::wstring BugReportView::GetDialogButtonLabel(
    MessageBoxFlags::DialogButton button) const {
  if (button == MessageBoxFlags::DIALOGBUTTON_OK) {
    if (problem_type_ == BugReportComboBoxModel::PHISHING_PAGE)
      return l10n_util::GetString(IDS_BUGREPORT_SEND_PHISHING_REPORT);
    else
      return l10n_util::GetString(IDS_BUGREPORT_SEND_REPORT);
  } else {
    return std::wstring();
  }
}

int BugReportView::GetDefaultDialogButton() const {
  return MessageBoxFlags::DIALOGBUTTON_NONE;
}

bool BugReportView::CanResize() const {
  return false;
}

bool BugReportView::CanMaximize() const {
  return false;
}

bool BugReportView::IsAlwaysOnTop() const {
  return false;
}

bool BugReportView::HasAlwaysOnTopMenu() const {
  return false;
}

bool BugReportView::IsModal() const {
  return true;
}

std::wstring BugReportView::GetWindowTitle() const {
  return l10n_util::GetString(IDS_BUGREPORT_TITLE);
}

bool BugReportView::Accept() {
  if (IsDialogButtonEnabled(MessageBoxFlags::DIALOGBUTTON_OK)) {
    if (problem_type_ == BugReportComboBoxModel::PHISHING_PAGE)
      BugReportUtil::ReportPhishing(tab_,
                                    WideToUTF8(page_url_text_->text()));
    else
      BugReportUtil::SendReport(profile_,
          WideToUTF8(page_title_text_->GetText()),
          problem_type_,
          WideToUTF8(page_url_text_->text()),
          WideToUTF8(description_text_->text()),
          include_page_image_checkbox_->checked() && png_data_.get() ?
              reinterpret_cast<const char *>(&((*png_data_.get())[0])) : NULL,
          png_data_->size());
  }
  return true;
}

views::View* BugReportView::GetContentsView() {
  return this;
}
<commit_msg>Change BugReportView to use the bug report types from the cross-platform BugReportUtil class.<commit_after>// Copyright (c) 2009 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/browser/views/bug_report_view.h"

#include "app/combobox_model.h"
#include "app/l10n_util.h"
#include "app/win_util.h"
#include "base/file_version_info.h"
#include "base/string_util.h"
#include "chrome/browser/bug_report_util.h"
#include "chrome/browser/net/url_fetcher.h"
#include "chrome/browser/profile.h"
#include "chrome/browser/safe_browsing/safe_browsing_util.h"
#include "chrome/browser/tab_contents/navigation_controller.h"
#include "chrome/browser/tab_contents/navigation_entry.h"
#include "chrome/browser/tab_contents/tab_contents.h"
#include "chrome/common/pref_names.h"
#include "chrome/common/pref_service.h"
#include "grit/chromium_strings.h"
#include "grit/generated_resources.h"
#include "grit/locale_settings.h"
#include "net/base/escape.h"
#include "unicode/locid.h"
#include "views/controls/button/checkbox.h"
#include "views/controls/label.h"
#include "views/grid_layout.h"
#include "views/standard_layout.h"
#include "views/widget/widget.h"
#include "views/window/client_view.h"
#include "views/window/window.h"

using views::ColumnSet;
using views::GridLayout;

// Report a bug data version.
static const int kBugReportVersion = 1;

// Number of lines description field can display at one time.
static const int kDescriptionLines = 5;

class BugReportComboBoxModel : public ComboboxModel {
 public:
  BugReportComboBoxModel() {}

  // ComboboxModel interface.
  virtual int GetItemCount() {
    return BugReportUtil::OTHER_PROBLEM + 1;
  }

  virtual std::wstring GetItemAt(int index) {
    return GetItemAtIndex(index);
  }

  static std::wstring GetItemAtIndex(int index) {
    switch (index) {
      case BugReportUtil::PAGE_WONT_LOAD:
        return l10n_util::GetString(IDS_BUGREPORT_PAGE_WONT_LOAD);
      case BugReportUtil::PAGE_LOOKS_ODD:
        return l10n_util::GetString(IDS_BUGREPORT_PAGE_LOOKS_ODD);
      case BugReportUtil::PHISHING_PAGE:
        return l10n_util::GetString(IDS_BUGREPORT_PHISHING_PAGE);
      case BugReportUtil::CANT_SIGN_IN:
        return l10n_util::GetString(IDS_BUGREPORT_CANT_SIGN_IN);
      case BugReportUtil::CHROME_MISBEHAVES:
        return l10n_util::GetString(IDS_BUGREPORT_CHROME_MISBEHAVES);
      case BugReportUtil::SOMETHING_MISSING:
        return l10n_util::GetString(IDS_BUGREPORT_SOMETHING_MISSING);
      case BugReportUtil::BROWSER_CRASH:
        return l10n_util::GetString(IDS_BUGREPORT_BROWSER_CRASH);
      case BugReportUtil::OTHER_PROBLEM:
        return l10n_util::GetString(IDS_BUGREPORT_OTHER_PROBLEM);
      default:
        NOTREACHED();
        return std::wstring();
    }
  }

 private:
  DISALLOW_COPY_AND_ASSIGN(BugReportComboBoxModel);
};

namespace browser {

// Global "display this dialog" function declared in browser_dialogs.h.
void ShowBugReportView(views::Widget* parent,
                       Profile* profile,
                       TabContents* tab) {
  BugReportView* view = new BugReportView(profile, tab);

  // Grab an exact snapshot of the window that the user is seeing (i.e. as
  // rendered--do not re-render, and include windowed plugins).
  std::vector<unsigned char> *screenshot_png = new std::vector<unsigned char>;
  win_util::GrabWindowSnapshot(parent->GetNativeView(), screenshot_png);
  // The BugReportView takes ownership of the png data, and will dispose of
  // it in its destructor.
  view->set_png_data(screenshot_png);

  // Create and show the dialog.
  views::Window::CreateChromeWindow(parent->GetNativeView(), gfx::Rect(),
                                    view)->Show();
}

}  // namespace browser

// BugReportView - create and submit a bug report from the user.
// This is separate from crash reporting, which is handled by Breakpad.
//
BugReportView::BugReportView(Profile* profile, TabContents* tab)
    : include_page_source_checkbox_(NULL),
      include_page_image_checkbox_(NULL),
      profile_(profile),
      tab_(tab),
      problem_type_(0) {
  DCHECK(profile);
  SetupControl();

  // We want to use the URL of the current committed entry (the current URL may
  // actually be the pending one).
  if (tab->controller().GetActiveEntry()) {
    page_url_text_->SetText(UTF8ToWide(
        tab->controller().GetActiveEntry()->url().spec()));
  }

  // Retrieve the application version info.
  scoped_ptr<FileVersionInfo> version_info(
      FileVersionInfo::CreateFileVersionInfoForCurrentModule());
  if (version_info.get()) {
    version_ = version_info->product_name() + L" - " +
        version_info->file_version() +
        L" (" + version_info->last_change() + L")";
  }
}

BugReportView::~BugReportView() {
}

void BugReportView::SetupControl() {
  bug_type_model_.reset(new BugReportComboBoxModel);

  // Adds all controls.
  bug_type_label_ = new views::Label(
      l10n_util::GetString(IDS_BUGREPORT_BUG_TYPE));
  bug_type_combo_ = new views::Combobox(bug_type_model_.get());
  bug_type_combo_->set_listener(this);

  page_title_label_ = new views::Label(
      l10n_util::GetString(IDS_BUGREPORT_REPORT_PAGE_TITLE));
  page_title_text_ = new views::Label(UTF16ToWideHack(tab_->GetTitle()));
  page_url_label_ = new views::Label(
      l10n_util::GetString(IDS_BUGREPORT_REPORT_URL_LABEL));
  // page_url_text_'s text (if any) is filled in after dialog creation.
  page_url_text_ = new views::Textfield;
  page_url_text_->SetController(this);

  description_label_ = new views::Label(
      l10n_util::GetString(IDS_BUGREPORT_DESCRIPTION_LABEL));
  description_text_ =
      new views::Textfield(views::Textfield::STYLE_MULTILINE);
  description_text_->SetHeightInLines(kDescriptionLines);

  include_page_source_checkbox_ = new views::Checkbox(
      l10n_util::GetString(IDS_BUGREPORT_INCLUDE_PAGE_SOURCE_CHKBOX));
  include_page_source_checkbox_->SetChecked(true);
  include_page_image_checkbox_ = new views::Checkbox(
      l10n_util::GetString(IDS_BUGREPORT_INCLUDE_PAGE_IMAGE_CHKBOX));
  include_page_image_checkbox_->SetChecked(true);

  // Arranges controls by using GridLayout.
  const int column_set_id = 0;
  GridLayout* layout = CreatePanelGridLayout(this);
  SetLayoutManager(layout);
  ColumnSet* column_set = layout->AddColumnSet(column_set_id);
  column_set->AddColumn(GridLayout::LEADING, GridLayout::FILL, 0,
                        GridLayout::USE_PREF, 0, 0);
  column_set->AddPaddingColumn(0, kRelatedControlHorizontalSpacing * 2);
  column_set->AddColumn(GridLayout::FILL, GridLayout::FILL, 1,
                        GridLayout::USE_PREF, 0, 0);

  // Page Title and text.
  layout->StartRow(0, column_set_id);
  layout->AddView(page_title_label_);
  layout->AddView(page_title_text_, 1, 1, GridLayout::LEADING,
                  GridLayout::FILL);
  layout->AddPaddingRow(0, kRelatedControlVerticalSpacing);

  // Bug type and combo box.
  layout->StartRow(0, column_set_id);
  layout->AddView(bug_type_label_, 1, 1, GridLayout::LEADING, GridLayout::FILL);
  layout->AddView(bug_type_combo_);
  layout->AddPaddingRow(0, kRelatedControlVerticalSpacing);

  // Page URL and text field.
  layout->StartRow(0, column_set_id);
  layout->AddView(page_url_label_);
  layout->AddView(page_url_text_);
  layout->AddPaddingRow(0, kRelatedControlVerticalSpacing);

  // Description label and text field.
  layout->StartRow(0, column_set_id);
  layout->AddView(description_label_, 1, 1, GridLayout::LEADING,
                  GridLayout::LEADING);
  layout->AddView(description_text_, 1, 1, GridLayout::FILL,
                  GridLayout::LEADING);
  layout->AddPaddingRow(0, kUnrelatedControlVerticalSpacing);

  // Checkboxes.
  // The include page source checkbox is hidden until we can make it work.
  // layout->StartRow(0, column_set_id);
  // layout->SkipColumns(1);
  // layout->AddView(include_page_source_checkbox_);
  // layout->AddPaddingRow(0, kRelatedControlVerticalSpacing);
  layout->StartRow(0, column_set_id);
  layout->SkipColumns(1);
  layout->AddView(include_page_image_checkbox_);
  layout->AddPaddingRow(0, kUnrelatedControlVerticalSpacing);
}

gfx::Size BugReportView::GetPreferredSize() {
  return gfx::Size(views::Window::GetLocalizedContentsSize(
      IDS_BUGREPORT_DIALOG_WIDTH_CHARS,
      IDS_BUGREPORT_DIALOG_HEIGHT_LINES));
}

void BugReportView::ItemChanged(views::Combobox* combobox,
                                int prev_index,
                                int new_index) {
  if (new_index == prev_index)
    return;

  problem_type_ = new_index;
  bool is_phishing_report = new_index == BugReportUtil::PHISHING_PAGE;

  description_text_->SetEnabled(!is_phishing_report);
  description_text_->SetReadOnly(is_phishing_report);
  if (is_phishing_report) {
    old_report_text_ = description_text_->text();
    description_text_->SetText(std::wstring());
  } else if (!old_report_text_.empty()) {
    description_text_->SetText(old_report_text_);
    old_report_text_.clear();
  }
  include_page_source_checkbox_->SetEnabled(!is_phishing_report);
  include_page_source_checkbox_->SetChecked(!is_phishing_report);
  include_page_image_checkbox_->SetEnabled(!is_phishing_report);
  include_page_image_checkbox_->SetChecked(!is_phishing_report);

  GetDialogClientView()->UpdateDialogButtons();
}

void BugReportView::ContentsChanged(views::Textfield* sender,
                                    const std::wstring& new_contents) {
}

bool BugReportView::HandleKeystroke(views::Textfield* sender,
                                    const views::Textfield::Keystroke& key) {
  return false;
}

std::wstring BugReportView::GetDialogButtonLabel(
    MessageBoxFlags::DialogButton button) const {
  if (button == MessageBoxFlags::DIALOGBUTTON_OK) {
    if (problem_type_ == BugReportUtil::PHISHING_PAGE)
      return l10n_util::GetString(IDS_BUGREPORT_SEND_PHISHING_REPORT);
    else
      return l10n_util::GetString(IDS_BUGREPORT_SEND_REPORT);
  } else {
    return std::wstring();
  }
}

int BugReportView::GetDefaultDialogButton() const {
  return MessageBoxFlags::DIALOGBUTTON_NONE;
}

bool BugReportView::CanResize() const {
  return false;
}

bool BugReportView::CanMaximize() const {
  return false;
}

bool BugReportView::IsAlwaysOnTop() const {
  return false;
}

bool BugReportView::HasAlwaysOnTopMenu() const {
  return false;
}

bool BugReportView::IsModal() const {
  return true;
}

std::wstring BugReportView::GetWindowTitle() const {
  return l10n_util::GetString(IDS_BUGREPORT_TITLE);
}

bool BugReportView::Accept() {
  if (IsDialogButtonEnabled(MessageBoxFlags::DIALOGBUTTON_OK)) {
    if (problem_type_ == BugReportUtil::PHISHING_PAGE)
      BugReportUtil::ReportPhishing(tab_,
                                    WideToUTF8(page_url_text_->text()));
    else
      BugReportUtil::SendReport(profile_,
          WideToUTF8(page_title_text_->GetText()),
          problem_type_,
          WideToUTF8(page_url_text_->text()),
          WideToUTF8(description_text_->text()),
          include_page_image_checkbox_->checked() && png_data_.get() ?
              reinterpret_cast<const char *>(&((*png_data_.get())[0])) : NULL,
          png_data_->size());
  }
  return true;
}

views::View* BugReportView::GetContentsView() {
  return this;
}
<|endoftext|>


<commit_before><commit_msg>check optimization flags, small fix<commit_after><|endoftext|>


<commit_before><commit_msg>Fix infinite loop in TileLayer update method when called with inconsistent state (zero view dimensions)<commit_after><|endoftext|>


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

// CLASS HEADER
#include <dali/internal/event/common/property-notification-impl.h>

// INTERNAL INCLUDES
#include <dali/internal/event/actors/actor-impl.h>
#include <dali/internal/event/common/object-impl.h>
#include <dali/internal/event/common/property-notification-manager.h>
#include <dali/internal/event/common/stage-impl.h>
#include <dali/internal/event/common/thread-local-storage.h>
#include <dali/internal/update/common/scene-graph-property-notification.h>
#include <dali/internal/update/manager/update-manager.h>
#include <dali/public-api/actors/actor.h>
#include <dali/public-api/common/dali-common.h>
#include <dali/public-api/math/radian.h>
#include <dali/public-api/math/vector2.h>

using Dali::Internal::SceneGraph::UpdateManager;

namespace Dali
{
namespace Internal
{
PropertyNotificationPtr PropertyNotification::New(Property&                      target,
                                                  int                            componentIndex,
                                                  const Dali::PropertyCondition& condition)
{
  ThreadLocalStorage& tls = ThreadLocalStorage::Get();

  UpdateManager& updateManager = tls.GetUpdateManager();

  PropertyNotificationManager& propertyNotificationManager = tls.GetPropertyNotificationManager();
  PropertyNotificationPtr      propertyNotification        = new PropertyNotification(updateManager,
                                                                          propertyNotificationManager,
                                                                          target,
                                                                          componentIndex,
                                                                          condition);
  return propertyNotification;
}

PropertyNotification::PropertyNotification(UpdateManager&                 updateManager,
                                           PropertyNotificationManager&   propertyNotificationManager,
                                           Property&                      target,
                                           int                            componentIndex,
                                           const Dali::PropertyCondition& condition)
: mUpdateManager(updateManager),
  mPropertyNotification(nullptr),
  mPropertyNotificationManager(propertyNotificationManager),
  mObjectPropertyIndex(target.propertyIndex),
  mPropertyType(Property::NONE),
  mComponentIndex(componentIndex),
  mCondition(condition),
  mNotifyMode(Dali::PropertyNotification::NOTIFY_ON_TRUE),
  mNotifyResult(false),
  mCompare(false)
{
  const Internal::PropertyCondition& conditionImpl = GetImplementation(condition);

  Dali::Vector<float>::SizeType count = conditionImpl.arguments.Count();
  for(Dali::Vector<float>::SizeType index = 0; index < count; ++index)
  {
    mRawConditionArgs.PushBack(conditionImpl.arguments[index]);
  }

  // Observe target object and create/destroy notification scene object accordingly.
  mObject = dynamic_cast<Object*>(&GetImplementation(target.object));
  if(mObject)
  {
    mPropertyType = mObject->GetPropertyType(mObjectPropertyIndex);

    int internalComponentIndex = mObject->GetPropertyComponentIndex(mObjectPropertyIndex);
    if(internalComponentIndex != Property::INVALID_COMPONENT_INDEX)
    {
      // override the one passed in
      mComponentIndex = internalComponentIndex;
    }
    if(mComponentIndex != Property::INVALID_COMPONENT_INDEX)
    {
      Property::Type type = mObject->GetPropertyType(mObjectPropertyIndex);
      if(type == Property::VECTOR2 || type == Property::VECTOR3 || type == Property::VECTOR4)
      {
        mPropertyType = Property::FLOAT;
      }
    }

    // In Size Property case, swapping components occurs sometimes.
    // To cover swapping components, previous and current components should be compared.
    if(mObjectPropertyIndex == Dali::Actor::Property::SIZE && mObject->GetPropertyType(mObjectPropertyIndex) == Property::VECTOR3)
    {
      mCompare = true;
      for(int i = 0; i < 3; ++i)
      {
        mRawConditionArgs.PushBack(0.0f);
      }
    }

    // all objects always have scene object
    CreateSceneObject();
  }

  // Connect to the property notification manager
  mPropertyNotificationManager.PropertyNotificationCreated(*this);
}

PropertyNotification::~PropertyNotification()
{
  Disable();

  // Guard to disallow use of PropertyNotificationManager after Core has been destroyed
  if(Stage::IsInstalled())
  {
    // Disconnect from the property notification manager
    mPropertyNotificationManager.PropertyNotificationDestroyed(*this);
  }
}

Dali::PropertyNotifySignalType& PropertyNotification::NotifySignal()
{
  return mNotifySignal;
}

void PropertyNotification::EmitSignalNotify()
{
  Dali::PropertyNotification source(this);

  mNotifySignal.Emit(source);
}

void PropertyNotification::Enable()
{
  CreateSceneObject();
}

void PropertyNotification::Disable()
{
  // Guard to allow handle destruction after Core has been destroyed
  if(Stage::IsInstalled())
  {
    // Stop scene-graph from monitoring the target's properties.
    DestroySceneObject();
  }
}

void PropertyNotification::SetNotifyResult(bool result)
{
  mNotifyResult = result;
}

const Dali::PropertyCondition& PropertyNotification::GetCondition() const
{
  return mCondition;
}

Dali::Handle PropertyNotification::GetTarget() const
{
  Dali::Handle handle(mObject);

  return handle;
}

Property::Index PropertyNotification::GetTargetProperty() const
{
  return mObjectPropertyIndex;
}

void PropertyNotification::SetNotifyMode(NotifyMode mode)
{
  mNotifyMode = mode;
  if(mPropertyNotification)
  {
    PropertyNotificationSetNotifyModeMessage(mUpdateManager, mPropertyNotification, mode);
  }
}

PropertyNotification::NotifyMode PropertyNotification::GetNotifyMode()
{
  return mNotifyMode;
}

bool PropertyNotification::GetNotifyResult() const
{
  return mNotifyResult;
}

bool PropertyNotification::CompareSceneObject(const SceneGraph::PropertyNotification* sceneObject)
{
  return sceneObject && sceneObject == mPropertyNotification;
}

void PropertyNotification::CreateSceneObject()
{
  // this method can be called from constructor and on stage connection
  if(!mPropertyNotification)
  {
    // Create a new PropertyNotification, keep a const pointer to it
    mPropertyNotification = SceneGraph::PropertyNotification::New(*mObject,
                                                                  mObjectPropertyIndex,
                                                                  mPropertyType,
                                                                  mComponentIndex,
                                                                  GetImplementation(mCondition).type,
                                                                  mRawConditionArgs,
                                                                  mNotifyMode,
                                                                  mCompare);
    OwnerPointer<SceneGraph::PropertyNotification> transferOwnership(const_cast<SceneGraph::PropertyNotification*>(mPropertyNotification));
    AddPropertyNotificationMessage(mUpdateManager, transferOwnership);
  }
}

void PropertyNotification::DestroySceneObject()
{
  if(mPropertyNotification != nullptr)
  {
    // Remove PropertyNotification using a message to the update manager
    RemovePropertyNotificationMessage(mUpdateManager, *mPropertyNotification);
    mPropertyNotification = nullptr;
  }
}

} // namespace Internal

} // namespace Dali
<commit_msg>Fix PropertyNotification issue<commit_after>/*
 * Copyright (c) 2021 Samsung Electronics Co., Ltd.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 */

// CLASS HEADER
#include <dali/internal/event/common/property-notification-impl.h>

// INTERNAL INCLUDES
#include <dali/internal/event/actors/actor-impl.h>
#include <dali/internal/event/common/object-impl.h>
#include <dali/internal/event/common/property-notification-manager.h>
#include <dali/internal/event/common/stage-impl.h>
#include <dali/internal/event/common/thread-local-storage.h>
#include <dali/internal/update/common/scene-graph-property-notification.h>
#include <dali/internal/update/manager/update-manager.h>
#include <dali/public-api/actors/actor.h>
#include <dali/public-api/common/dali-common.h>
#include <dali/public-api/math/radian.h>
#include <dali/public-api/math/vector2.h>

using Dali::Internal::SceneGraph::UpdateManager;

namespace Dali
{
namespace Internal
{
PropertyNotificationPtr PropertyNotification::New(Property&                      target,
                                                  int                            componentIndex,
                                                  const Dali::PropertyCondition& condition)
{
  ThreadLocalStorage& tls = ThreadLocalStorage::Get();

  UpdateManager& updateManager = tls.GetUpdateManager();

  PropertyNotificationManager& propertyNotificationManager = tls.GetPropertyNotificationManager();
  PropertyNotificationPtr      propertyNotification        = new PropertyNotification(updateManager,
                                                                          propertyNotificationManager,
                                                                          target,
                                                                          componentIndex,
                                                                          condition);
  return propertyNotification;
}

PropertyNotification::PropertyNotification(UpdateManager&                 updateManager,
                                           PropertyNotificationManager&   propertyNotificationManager,
                                           Property&                      target,
                                           int                            componentIndex,
                                           const Dali::PropertyCondition& condition)
: mUpdateManager(updateManager),
  mPropertyNotification(nullptr),
  mPropertyNotificationManager(propertyNotificationManager),
  mObjectPropertyIndex(target.propertyIndex),
  mPropertyType(Property::NONE),
  mComponentIndex(componentIndex),
  mCondition(condition),
  mNotifyMode(Dali::PropertyNotification::NOTIFY_ON_TRUE),
  mNotifyResult(false),
  mCompare(false)
{
  const Internal::PropertyCondition& conditionImpl = GetImplementation(condition);

  Dali::Vector<float>::SizeType count = conditionImpl.arguments.Count();
  for(Dali::Vector<float>::SizeType index = 0; index < count; ++index)
  {
    mRawConditionArgs.PushBack(conditionImpl.arguments[index]);
  }

  // Observe target object and create/destroy notification scene object accordingly.
  mObject = dynamic_cast<Object*>(&GetImplementation(target.object));
  if(mObject)
  {
    mPropertyType = mObject->GetPropertyType(mObjectPropertyIndex);

    int internalComponentIndex = mObject->GetPropertyComponentIndex(mObjectPropertyIndex);
    if(internalComponentIndex != Property::INVALID_COMPONENT_INDEX)
    {
      // override the one passed in
      mComponentIndex = internalComponentIndex;
    }
    if(mComponentIndex != Property::INVALID_COMPONENT_INDEX)
    {
      Property::Type type = mObject->GetPropertyType(mObjectPropertyIndex);
      if(type == Property::VECTOR2 || type == Property::VECTOR3 || type == Property::VECTOR4)
      {
        mPropertyType = Property::FLOAT;
      }
    }

    // To cover swapping components, previous and current components should be compared.
    if(mObject->GetPropertyType(mObjectPropertyIndex) == Property::VECTOR3)
    {
      mCompare = true;
      for(int i = 0; i < 3; ++i)
      {
        mRawConditionArgs.PushBack(0.0f);
      }
    }

    // all objects always have scene object
    CreateSceneObject();
  }

  // Connect to the property notification manager
  mPropertyNotificationManager.PropertyNotificationCreated(*this);
}

PropertyNotification::~PropertyNotification()
{
  Disable();

  // Guard to disallow use of PropertyNotificationManager after Core has been destroyed
  if(Stage::IsInstalled())
  {
    // Disconnect from the property notification manager
    mPropertyNotificationManager.PropertyNotificationDestroyed(*this);
  }
}

Dali::PropertyNotifySignalType& PropertyNotification::NotifySignal()
{
  return mNotifySignal;
}

void PropertyNotification::EmitSignalNotify()
{
  Dali::PropertyNotification source(this);

  mNotifySignal.Emit(source);
}

void PropertyNotification::Enable()
{
  CreateSceneObject();
}

void PropertyNotification::Disable()
{
  // Guard to allow handle destruction after Core has been destroyed
  if(Stage::IsInstalled())
  {
    // Stop scene-graph from monitoring the target's properties.
    DestroySceneObject();
  }
}

void PropertyNotification::SetNotifyResult(bool result)
{
  mNotifyResult = result;
}

const Dali::PropertyCondition& PropertyNotification::GetCondition() const
{
  return mCondition;
}

Dali::Handle PropertyNotification::GetTarget() const
{
  Dali::Handle handle(mObject);

  return handle;
}

Property::Index PropertyNotification::GetTargetProperty() const
{
  return mObjectPropertyIndex;
}

void PropertyNotification::SetNotifyMode(NotifyMode mode)
{
  mNotifyMode = mode;
  if(mPropertyNotification)
  {
    PropertyNotificationSetNotifyModeMessage(mUpdateManager, mPropertyNotification, mode);
  }
}

PropertyNotification::NotifyMode PropertyNotification::GetNotifyMode()
{
  return mNotifyMode;
}

bool PropertyNotification::GetNotifyResult() const
{
  return mNotifyResult;
}

bool PropertyNotification::CompareSceneObject(const SceneGraph::PropertyNotification* sceneObject)
{
  return sceneObject && sceneObject == mPropertyNotification;
}

void PropertyNotification::CreateSceneObject()
{
  // this method can be called from constructor and on stage connection
  if(!mPropertyNotification)
  {
    // Create a new PropertyNotification, keep a const pointer to it
    mPropertyNotification = SceneGraph::PropertyNotification::New(*mObject,
                                                                  mObjectPropertyIndex,
                                                                  mPropertyType,
                                                                  mComponentIndex,
                                                                  GetImplementation(mCondition).type,
                                                                  mRawConditionArgs,
                                                                  mNotifyMode,
                                                                  mCompare);
    OwnerPointer<SceneGraph::PropertyNotification> transferOwnership(const_cast<SceneGraph::PropertyNotification*>(mPropertyNotification));
    AddPropertyNotificationMessage(mUpdateManager, transferOwnership);
  }
}

void PropertyNotification::DestroySceneObject()
{
  if(mPropertyNotification != nullptr)
  {
    // Remove PropertyNotification using a message to the update manager
    RemovePropertyNotificationMessage(mUpdateManager, *mPropertyNotification);
    mPropertyNotification = nullptr;
  }
}

} // namespace Internal

} // namespace Dali
<|endoftext|>


<commit_before>/*
Copyright (c) 2015 - present Advanced Micro Devices, Inc. All rights reserved.

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/

#include <hip/hip_runtime.h>

#include "hip_internal.hpp"
#include "platform/program.hpp"
#include "platform/runtime.hpp"

constexpr unsigned __cudaFatMAGIC  = 0x1ee55a01;
constexpr unsigned __cudaFatMAGIC2 = 0x466243b1;
constexpr unsigned __cudaFatMAGIC3 = 0xba55ed50;

struct __CudaFatBinaryWrapper {
  unsigned int magic;
  unsigned int version;
  void*        binary;
  void*        dummy1;
};

struct __CudaFatBinaryHeader {
  unsigned int           magic;
  unsigned short         version;
  unsigned short         headerSize;
  unsigned long long int fatSize;
};

struct __CudaPartHeader {
  unsigned short         type;
  unsigned short         dummy1;
  unsigned int           headerSize;
  unsigned long long int partSize;
  unsigned long long int dummy2;
  unsigned int           dummy3;
  unsigned int           subarch;
};

static hipModule_t registerCudaFatBinary(const __CudaFatBinaryHeader* fbheader)
{
  const __CudaPartHeader* pheader = reinterpret_cast<const __CudaPartHeader*>(
      reinterpret_cast<uintptr_t>(fbheader) + fbheader->headerSize);
  const __CudaPartHeader* end = reinterpret_cast<const __CudaPartHeader*>(
      reinterpret_cast<uintptr_t>(pheader) + fbheader->fatSize);

  amd::Program* program = new amd::Program(*g_context);
  if (!program) return nullptr;

  while (pheader < end) {
    if (true/*pheader->subarch == match a device in the context*/) {
      const void *image = reinterpret_cast<void*>(
          reinterpret_cast<uintptr_t>(pheader) + pheader->headerSize);
      size_t size = pheader->partSize;
      if (CL_SUCCESS != program->addDeviceProgram(*g_context->devices()[0], image, size) ||
        CL_SUCCESS != program->build(g_context->devices(), nullptr, nullptr, nullptr)) {
        return nullptr;
      }
      break;
    }
    pheader = reinterpret_cast<const __CudaPartHeader*>(
        reinterpret_cast<uintptr_t>(pheader) + pheader->headerSize + pheader->partSize);
  }

  return reinterpret_cast<hipModule_t>(as_cl(program));
}

#define CLANG_OFFLOAD_BUNDLER_MAGIC_STR "__CLANG_OFFLOAD_BUNDLE__"
#define AMDGCN_AMDHSA_TRIPLE "openmp-amdgcn--amdhsa"

struct __ClangOffloadBundleDesc {
  uint64_t offset;
  uint64_t size;
  uint64_t tripleSize;
  const char triple[1];
};

struct __ClangOffloadBundleHeader {
  const char magic[sizeof(CLANG_OFFLOAD_BUNDLER_MAGIC_STR) - 1];
  uint64_t numBundles;
  __ClangOffloadBundleDesc desc[1];
};

static hipModule_t registerOffloadBundle(const __ClangOffloadBundleHeader* obheader)
{
  amd::Program* program = new amd::Program(*g_context);
  if (!program)
    return nullptr;

  const __ClangOffloadBundleDesc* desc = &obheader->desc[0];
  for (uint64_t i = 0; i < obheader->numBundles; ++i,
       desc = reinterpret_cast<const __ClangOffloadBundleDesc*>(
           reinterpret_cast<uintptr_t>(&desc->triple[0]) + desc->tripleSize)) {

    std::string triple(desc->triple, sizeof(AMDGCN_AMDHSA_TRIPLE) - 1);
    if (triple.compare(AMDGCN_AMDHSA_TRIPLE))
      continue;

    std::string target(desc->triple + sizeof(AMDGCN_AMDHSA_TRIPLE),
                       desc->tripleSize - sizeof(AMDGCN_AMDHSA_TRIPLE));
    if (target.compare(g_context->devices()[0]->info().name_))
      continue;

    const void *image = reinterpret_cast<const void*>(
        reinterpret_cast<uintptr_t>(obheader) + desc->offset);
    size_t size = desc->size;

    if (CL_SUCCESS == program->addDeviceProgram(*g_context->devices()[0], image, size) &&
        CL_SUCCESS == program->build(g_context->devices(), nullptr, nullptr, nullptr))
      break;
  }

  return reinterpret_cast<hipModule_t>(as_cl(program));
}

extern "C" hipModule_t __hipRegisterFatBinary(const void* data)
{
  HIP_INIT();

  const __CudaFatBinaryWrapper* fbwrapper = reinterpret_cast<const __CudaFatBinaryWrapper*>(data);
  if (fbwrapper->magic != __cudaFatMAGIC2 || fbwrapper->version != 1) {
    return nullptr;
  }
  const __CudaFatBinaryHeader* fbheader = reinterpret_cast<const __CudaFatBinaryHeader*>(fbwrapper->binary);
  if (fbheader->magic == __cudaFatMAGIC3 && fbheader->version == 1) {
    return registerCudaFatBinary(fbheader);
  }

  std::string magic((char*)fbwrapper->binary, sizeof(CLANG_OFFLOAD_BUNDLER_MAGIC_STR) - 1);
  if (!magic.compare(CLANG_OFFLOAD_BUNDLER_MAGIC_STR)) {
    return registerOffloadBundle(reinterpret_cast<const __ClangOffloadBundleHeader*>(fbwrapper->binary));
  }

  return nullptr;
}

std::map<const void*, hipFunction_t> g_functions;

extern "C" void __hipRegisterFunction(
  hipModule_t  module,
  const void*  hostFunction,
  char*        deviceFunction,
  const char*  deviceName,
  unsigned int threadLimit,
  uint3*       tid,
  uint3*       bid,
  dim3*        blockDim,
  dim3*        gridDim,
  int*         wSize)
{
  HIP_INIT();

  amd::Program* program = as_amd(reinterpret_cast<cl_program>(module));

  const amd::Symbol* symbol = program->findSymbol(deviceName);
  if (!symbol) return;

  amd::Kernel* kernel = new amd::Kernel(*program, *symbol, deviceName);
  if (!kernel) return;

  // FIXME: not thread safe
  g_functions.insert(std::make_pair(hostFunction, reinterpret_cast<hipFunction_t>(as_cl(kernel))));
}

extern "C" void __hipRegisterVar(
  hipModule_t module,
  char*       hostVar,
  char*       deviceVar,
  const char* deviceName,
  int         ext,
  int         size,
  int         constant,
  int         global)
{
  HIP_INIT();
}

extern "C" void __hipUnregisterFatBinary(
  hipModule_t module
)
{
  HIP_INIT();
}

dim3 g_gridDim; // FIXME: place in execution stack
dim3 g_blockDim; // FIXME: place in execution stack
size_t g_sharedMem; // FIXME: place in execution stack
hipStream_t g_stream; // FIXME: place in execution stack

extern "C" hipError_t hipConfigureCall(
  dim3 gridDim,
  dim3 blockDim,
  size_t sharedMem,
  hipStream_t stream)
{
  HIP_INIT_API(gridDim, blockDim, sharedMem, stream);

  // FIXME: should push and new entry on the execution stack

  g_gridDim = gridDim;
  g_blockDim = blockDim;
  g_sharedMem = sharedMem;
  g_stream = stream;

  return hipSuccess;
}

char* g_arguments[1024]; // FIXME: needs to grow

extern "C" hipError_t hipSetupArgument(
  const void *arg,
  size_t size,
  size_t offset)
{
  HIP_INIT_API(arg, size, offset);

  // FIXME: should modify the top of the execution stack

  ::memcpy(g_arguments + offset, arg, size);
  return hipSuccess;
}

extern "C" hipError_t hipLaunchByPtr(const void *hostFunction)
{
  HIP_INIT_API(hostFunction);

  const auto it = g_functions.find(hostFunction);
  if (it == g_functions.cend())
    return hipErrorUnknown;

  // FIXME: should pop an entry from the execution stack

  void *extra[] = {
      HIP_LAUNCH_PARAM_BUFFER_POINTER, g_arguments,
      HIP_LAUNCH_PARAM_BUFFER_SIZE, 0 /* FIXME: not needed, but should be correct*/,
      HIP_LAUNCH_PARAM_END
    };

  return hipModuleLaunchKernel(it->second,
    g_gridDim.x, g_gridDim.y, g_gridDim.z,
    g_blockDim.x, g_blockDim.y, g_blockDim.z,
    g_sharedMem, g_stream, nullptr, extra);
}

#if defined(ATI_OS_LINUX)

namespace hip_impl {

void hipLaunchKernelGGLImpl(
  uintptr_t function_address,
  const dim3& numBlocks,
  const dim3& dimBlocks,
  uint32_t sharedMemBytes,
  hipStream_t stream,
  void** kernarg) {

  assert(0 && "Unimplemented");
}

}

#endif // defined(ATI_OS_LINUX)
<commit_msg>P4 to Git Change 1547563 by lmoriche@lmoriche_opencl_dev2 on 2018/04/27 21:10:47<commit_after>/*
Copyright (c) 2015 - present Advanced Micro Devices, Inc. All rights reserved.

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/

#include <hip/hip_runtime.h>

#include "hip_internal.hpp"
#include "platform/program.hpp"
#include "platform/runtime.hpp"

#include <unordered_map>
#include "elfio.hpp"

constexpr unsigned __cudaFatMAGIC2 = 0x466243b1;

struct __CudaFatBinaryWrapper {
  unsigned int magic;
  unsigned int version;
  void*        binary;
  void*        dummy1;
};

#define CLANG_OFFLOAD_BUNDLER_MAGIC_STR "__CLANG_OFFLOAD_BUNDLE__"
#define OPENMP_AMDGCN_AMDHSA_TRIPLE "openmp-amdgcn--amdhsa"
#define HCC_AMDGCN_AMDHSA_TRIPLE "hcc-amdgcn--amdhsa"

struct __ClangOffloadBundleDesc {
  uint64_t offset;
  uint64_t size;
  uint64_t tripleSize;
  const char triple[1];
};

struct __ClangOffloadBundleHeader {
  const char magic[sizeof(CLANG_OFFLOAD_BUNDLER_MAGIC_STR) - 1];
  uint64_t numBundles;
  __ClangOffloadBundleDesc desc[1];
};

extern "C" hipModule_t __hipRegisterFatBinary(const void* data)
{
  HIP_INIT();

  const __CudaFatBinaryWrapper* fbwrapper = reinterpret_cast<const __CudaFatBinaryWrapper*>(data);
  if (fbwrapper->magic != __cudaFatMAGIC2 || fbwrapper->version != 1) {
    return nullptr;
  }
  std::string magic((char*)fbwrapper->binary, sizeof(CLANG_OFFLOAD_BUNDLER_MAGIC_STR) - 1);
  if (magic.compare(CLANG_OFFLOAD_BUNDLER_MAGIC_STR)) {
    return nullptr;
  }

  amd::Program* program = new amd::Program(*g_context);
  if (!program)
    return nullptr;

  const auto obheader = reinterpret_cast<const __ClangOffloadBundleHeader*>(fbwrapper->binary);
  const auto* desc = &obheader->desc[0];
  for (uint64_t i = 0; i < obheader->numBundles; ++i,
       desc = reinterpret_cast<const __ClangOffloadBundleDesc*>(
           reinterpret_cast<uintptr_t>(&desc->triple[0]) + desc->tripleSize)) {

    std::string triple(desc->triple, sizeof(OPENMP_AMDGCN_AMDHSA_TRIPLE) - 1);
    if (triple.compare(OPENMP_AMDGCN_AMDHSA_TRIPLE))
      continue;

    std::string target(desc->triple + sizeof(OPENMP_AMDGCN_AMDHSA_TRIPLE),
                       desc->tripleSize - sizeof(OPENMP_AMDGCN_AMDHSA_TRIPLE));
    if (target.compare(g_context->devices()[0]->info().name_))
      continue;

    const void *image = reinterpret_cast<const void*>(
        reinterpret_cast<uintptr_t>(obheader) + desc->offset);
    size_t size = desc->size;

    if (CL_SUCCESS == program->addDeviceProgram(*g_context->devices()[0], image, size) &&
        CL_SUCCESS == program->build(g_context->devices(), nullptr, nullptr, nullptr))
      break;
  }

  return reinterpret_cast<hipModule_t>(as_cl(program));
}

std::map<const void*, hipFunction_t> g_functions;

extern "C" void __hipRegisterFunction(
  hipModule_t  module,
  const void*  hostFunction,
  char*        deviceFunction,
  const char*  deviceName,
  unsigned int threadLimit,
  uint3*       tid,
  uint3*       bid,
  dim3*        blockDim,
  dim3*        gridDim,
  int*         wSize)
{
  HIP_INIT();

  amd::Program* program = as_amd(reinterpret_cast<cl_program>(module));

  const amd::Symbol* symbol = program->findSymbol(deviceName);
  if (!symbol) return;

  amd::Kernel* kernel = new amd::Kernel(*program, *symbol, deviceName);
  if (!kernel) return;

  // FIXME: not thread safe
  g_functions.insert(std::make_pair(hostFunction, reinterpret_cast<hipFunction_t>(as_cl(kernel))));
}

extern "C" void __hipRegisterVar(
  hipModule_t module,
  char*       hostVar,
  char*       deviceVar,
  const char* deviceName,
  int         ext,
  int         size,
  int         constant,
  int         global)
{
  HIP_INIT();
}

extern "C" void __hipUnregisterFatBinary(
  hipModule_t module
)
{
  HIP_INIT();
}

dim3 g_gridDim; // FIXME: place in execution stack
dim3 g_blockDim; // FIXME: place in execution stack
size_t g_sharedMem; // FIXME: place in execution stack
hipStream_t g_stream; // FIXME: place in execution stack

extern "C" hipError_t hipConfigureCall(
  dim3 gridDim,
  dim3 blockDim,
  size_t sharedMem,
  hipStream_t stream)
{
  HIP_INIT_API(gridDim, blockDim, sharedMem, stream);

  // FIXME: should push and new entry on the execution stack

  g_gridDim = gridDim;
  g_blockDim = blockDim;
  g_sharedMem = sharedMem;
  g_stream = stream;

  return hipSuccess;
}

char* g_arguments[1024]; // FIXME: needs to grow

extern "C" hipError_t hipSetupArgument(
  const void *arg,
  size_t size,
  size_t offset)
{
  HIP_INIT_API(arg, size, offset);

  // FIXME: should modify the top of the execution stack

  ::memcpy(g_arguments + offset, arg, size);
  return hipSuccess;
}

extern "C" hipError_t hipLaunchByPtr(const void *hostFunction)
{
  HIP_INIT_API(hostFunction);

  const auto it = g_functions.find(hostFunction);
  if (it == g_functions.cend())
    return hipErrorUnknown;

  // FIXME: should pop an entry from the execution stack

  void *extra[] = {
      HIP_LAUNCH_PARAM_BUFFER_POINTER, g_arguments,
      HIP_LAUNCH_PARAM_BUFFER_SIZE, 0 /* FIXME: not needed, but should be correct*/,
      HIP_LAUNCH_PARAM_END
    };

  return hipModuleLaunchKernel(it->second,
    g_gridDim.x, g_gridDim.y, g_gridDim.z,
    g_blockDim.x, g_blockDim.y, g_blockDim.z,
    g_sharedMem, g_stream, nullptr, extra);
}

#if defined(ATI_OS_LINUX)

namespace hip_impl {

struct dl_phdr_info {
  ELFIO::Elf64_Addr        dlpi_addr;
  const char       *dlpi_name;
  const ELFIO::Elf64_Phdr *dlpi_phdr;
  ELFIO::Elf64_Half        dlpi_phnum;
};

extern "C" int dl_iterate_phdr(
  int (*callback) (struct dl_phdr_info *info, size_t size, void *data), void *data
);

struct Symbol {
  std::string name;
  ELFIO::Elf64_Addr value = 0;
  ELFIO::Elf_Xword size = 0;
  ELFIO::Elf_Half sect_idx = 0;
  uint8_t bind = 0;
  uint8_t type = 0;
  uint8_t other = 0;
};

inline Symbol read_symbol(const ELFIO::symbol_section_accessor& section, unsigned int idx) {
  assert(idx < section.get_symbols_num());

  Symbol r;
  section.get_symbol(idx, r.name, r.value, r.size, r.bind, r.type, r.sect_idx, r.other);

  return r;
}

template <typename P>
inline ELFIO::section* find_section_if(ELFIO::elfio& reader, P p) {
    const auto it = find_if(reader.sections.begin(), reader.sections.end(), std::move(p));

    return it != reader.sections.end() ? *it : nullptr;
}

std::vector<std::pair<uintptr_t, std::string>> function_names_for(const ELFIO::elfio& reader,
                                                                  ELFIO::section* symtab) {
  std::vector<std::pair<uintptr_t, std::string>> r;
  ELFIO::symbol_section_accessor symbols{reader, symtab};

  for (auto i = 0u; i != symbols.get_symbols_num(); ++i) {
    auto tmp = read_symbol(symbols, i);

    if (tmp.type == STT_FUNC && tmp.sect_idx != SHN_UNDEF && !tmp.name.empty()) {
      r.emplace_back(tmp.value, tmp.name);
    }
  }

  return r;
}

const std::vector<std::pair<uintptr_t, std::string>>& function_names_for_process() {
  static constexpr const char self[] = "/proc/self/exe";

  static std::vector<std::pair<uintptr_t, std::string>> r;
  static std::once_flag f;

  std::call_once(f, []() {
    ELFIO::elfio reader;

    if (reader.load(self)) {
      const auto it = find_section_if(
          reader, [](const ELFIO::section* x) { return x->get_type() == SHT_SYMTAB; });

      if (it) r = function_names_for(reader, it);
    }
  });

  return r;
}

const std::unordered_map<uintptr_t, std::string>& function_names()
{
  static std::unordered_map<uintptr_t, std::string> r{
    function_names_for_process().cbegin(),
    function_names_for_process().cend()};
  static std::once_flag f;

  std::call_once(f, []() {
    dl_iterate_phdr([](dl_phdr_info* info, size_t, void*) {
      ELFIO::elfio reader;

      if (reader.load(info->dlpi_name)) {
        const auto it = find_section_if(
            reader, [](const ELFIO::section* x) { return x->get_type() == SHT_SYMTAB; });

        if (it) {
          auto n = function_names_for(reader, it);

          for (auto&& f : n) f.first += info->dlpi_addr;

          r.insert(make_move_iterator(n.begin()), make_move_iterator(n.end()));
        }
      }
      return 0;
    },
    nullptr);
  });

  return r;
}

std::vector<char> bundles_for_process() {
  static constexpr const char self[] = "/proc/self/exe";
  static constexpr const char kernel_section[] = ".kernel";
  std::vector<char> r;

  ELFIO::elfio reader;

  if (reader.load(self)) {
    auto it = find_section_if(
        reader, [](const ELFIO::section* x) { return x->get_name() == kernel_section; });

    if (it) r.insert(r.end(), it->get_data(), it->get_data() + it->get_size());
  }

  return r;
}

const std::vector<hipModule_t>& modules() {
    static std::vector<hipModule_t> r;
    static std::once_flag f;

    std::call_once(f, []() {
      static std::vector<std::vector<char>> bundles{bundles_for_process()};

      dl_iterate_phdr(
          [](dl_phdr_info* info, std::size_t, void*) {
        ELFIO::elfio tmp;
        if (tmp.load(info->dlpi_name)) {
          const auto it = find_section_if(
              tmp, [](const ELFIO::section* x) { return x->get_name() == ".kernel"; });

          if (it) bundles.emplace_back(it->get_data(), it->get_data() + it->get_size());
        }
        return 0;
      },
      nullptr);

      for (auto&& bundle : bundles) {
        std::string magic(&bundle[0], sizeof(CLANG_OFFLOAD_BUNDLER_MAGIC_STR) - 1);
        if (magic.compare(CLANG_OFFLOAD_BUNDLER_MAGIC_STR))
          continue;

        const auto obheader = reinterpret_cast<const __ClangOffloadBundleHeader*>(&bundle[0]);
        const auto* desc = &obheader->desc[0];
        for (uint64_t i = 0; i < obheader->numBundles; ++i,
             desc = reinterpret_cast<const __ClangOffloadBundleDesc*>(
                 reinterpret_cast<uintptr_t>(&desc->triple[0]) + desc->tripleSize)) {

          std::string triple(desc->triple, sizeof(HCC_AMDGCN_AMDHSA_TRIPLE) - 1);
          if (triple.compare(HCC_AMDGCN_AMDHSA_TRIPLE))
            continue;

          std::string target(desc->triple + sizeof(HCC_AMDGCN_AMDHSA_TRIPLE),
                             desc->tripleSize - sizeof(HCC_AMDGCN_AMDHSA_TRIPLE));

          if (!target.compare(g_context->devices()[0]->info().name_)) {
            hipModule_t module;
            if (hipSuccess == hipModuleLoadData(&module, reinterpret_cast<const void*>(
                reinterpret_cast<uintptr_t>(obheader) + desc->offset)))
              r.push_back(module);
              break;
          }
        }
      }
    });

    return r;
}

const std::unordered_map<uintptr_t, hipFunction_t>& functions()
{
  static std::unordered_map<uintptr_t, hipFunction_t> r;
  static std::once_flag f;

  std::call_once(f, []() {
    for (auto&& function : function_names()) {
      for (auto&& module : modules()) {
        hipFunction_t f;
        if (hipSuccess == hipModuleGetFunction(&f, module, function.second.c_str()))
          r[function.first] = f;
      }
    }
  });

  return r;
}

void hipLaunchKernelGGLImpl(
  uintptr_t function_address,
  const dim3& numBlocks,
  const dim3& dimBlocks,
  uint32_t sharedMemBytes,
  hipStream_t stream,
  void** kernarg)
{
  HIP_INIT();

  const auto it = functions().find(function_address);
  if (it == functions().cend())
    return;

  hipModuleLaunchKernel(it->second,
    numBlocks.x, numBlocks.y, numBlocks.z,
    dimBlocks.x, dimBlocks.y, dimBlocks.z,
    sharedMemBytes, stream, nullptr, kernarg);
}

}

#endif // defined(ATI_OS_LINUX)
<|endoftext|>