<commit_before>#include <sys/types.h>
#include <sys/socket.h>
#include <unistd.h>
#include <string.h>
#include "cmm_internal_listener.h"
#include "cmm_socket.private.h"
#include "csocket_mapping.h"
#include "debug.h"
#include <netinet/in.h>
#include <arpa/inet.h>

#define INTERNAL_LISTEN_PORT 42424

ListenerThread::ListenerThread(CMMSocketImpl *sk_)
    : sk(sk_)
{
    struct sockaddr_in bind_addr;
    memset(&bind_addr, 0, sizeof(bind_addr));
    bind_addr.sin_addr.s_addr = INADDR_ANY;
    bind_addr.sin_port = htons(INTERNAL_LISTEN_PORT);

    listener_sock = socket(PF_INET, SOCK_STREAM, 0);
    if (listener_sock < 0) {
        throw -1;
    }

    int on = 1;
    int rc = setsockopt(listener_sock, SOL_SOCKET, SO_REUSEADDR,
                        (char *) &on, sizeof(on));
    if (rc < 0) {
        dbgprintf("Cannot reuse socket address\n");
    }

    do {
	rc = bind(listener_sock,
		  (struct sockaddr *)&bind_addr, sizeof(bind_addr));
	if (rc < 0) {
            //if (bind_addr.sin_port == htons(INTERNAL_LISTEN_PORT)) {
            bind_addr.sin_port = htons(ntohs(bind_addr.sin_port) + 1);
            //} else {
            //break;
            //}
	}
    } while (rc < 0);

    if (rc < 0) {
	perror("bind");
	dbgprintf("Listener failed to bind!\n");
	close(listener_sock);
	throw rc;
    }
    dbgprintf("Listener bound to port %d\n", ntohs(bind_addr.sin_port));

    socklen_t addrlen = sizeof(bind_addr);
    rc = getsockname(listener_sock,
                     (struct sockaddr *)&bind_addr, &addrlen);
    if (rc < 0) {
        perror("getsockname");
	dbgprintf("Couldn't get local listener sockaddr!\n");
        close(listener_sock);
        throw rc;
    }
    listen_port = bind_addr.sin_port;
    rc = listen(listener_sock, 5);
    if (rc < 0) {
        close(listener_sock);
        throw rc;
    }
    dbgprintf("Internal socket listener listening up on port %d\n",
              ntohs(listen_port));
}

void
ListenerThread::stop()
{
    dbgprintf("Shutting down listener %d (port %d)\n",
              listener_sock, ntohs(listen_port));
    shutdown(listener_sock, SHUT_RDWR);
    //stop();
    //join();
    //close(listener_sock);
}

in_port_t
ListenerThread::port() const
{
    return listen_port;
}

void
ListenerThread::Run()
{
    char name[MAX_NAME_LEN+1];
    memset(name, 0, MAX_NAME_LEN+1);
    snprintf(name, MAX_NAME_LEN, "Listener %d", listener_sock);
    set_thread_name(name);

    // we never join to this thread; we synchronize with its death
    // with a condition variable.
    detach();

    while (1) {
        fd_set readfds;
        FD_ZERO(&readfds);
        FD_SET(listener_sock, &readfds);
        int rc = select(listener_sock + 1, &readfds, NULL, NULL, NULL);
	if (rc < 0) {
	    if (errno == EINTR) {
		continue;
	    } else {
                close(listener_sock);
                //dbgprintf("Exiting.\n");
		return;
	    }
	}

        struct sockaddr_in remote_addr;
        socklen_t addrlen = sizeof(remote_addr);
        int sock = accept(listener_sock,
                          (struct sockaddr *)&remote_addr, &addrlen);
        if (sock < 0) {
            dbgprintf("Listener socket shutdown, listener thread exiting,"
                      " errno=%d\n",errno);
	    close(listener_sock);
            //throw std::runtime_error("Socket error");
            //dbgprintf("Exiting.\n");
            return;
        }

        struct sockaddr_in local_addr;
        rc = getsockname(sock,
                         (struct sockaddr *)&local_addr, &addrlen);
        if (rc < 0) {
            perror("getsockname");
            close(sock);
            dbgprintf("Error getting local socket address\n");
            continue;
        }

        dbgprintf("Remote host %s is connecting ",
                  inet_ntoa(remote_addr.sin_addr));
        dbgprintf_plain("to local address %s\n",
                  inet_ntoa(local_addr.sin_addr));
        struct net_interface dummy;
        if (!sk->csock_map->get_local_iface_by_addr(local_addr.sin_addr, dummy)) {
            dbgprintf("%s: network should be down.  ",
                      inet_ntoa(local_addr.sin_addr));
            dbgprintf_plain("%s, go away.\n",
                            inet_ntoa(remote_addr.sin_addr));
            close(sock);
            continue;
        }

        struct CMMSocketControlHdr hdr;
        rc = recv(sock, &hdr, sizeof(hdr), MSG_WAITALL);
        if (rc != sizeof(hdr)) {
            perror("recv");
            close(sock);
            dbgprintf("error receiving new_interface data\n");
            continue;
        }

        if (ntohs(hdr.type) != CMM_CONTROL_MSG_NEW_INTERFACE) {
            dbgprintf("Expected new-interface message on "
                      "connection start;\n   Got %s\n",
                      hdr.describe().c_str());
            close(sock);
            continue;
        }

        struct net_interface remote_iface = { hdr.op.new_interface.ip_addr,
                                              ntohl(hdr.op.new_interface.labels),
                                              ntohl(hdr.op.new_interface.bandwidth),
                                              ntohl(hdr.op.new_interface.RTT)};

        struct sockaddr_in true_remote_addr;
        memcpy(&true_remote_addr.sin_addr, &hdr.op.new_interface.ip_addr,
               sizeof(struct in_addr));
        dbgprintf("Adding connection %d from %s ",
                  sock, inet_ntoa(true_remote_addr.sin_addr));
        dbgprintf_plain("(peername %s)\n",
                        inet_ntoa(remote_addr.sin_addr));

        try {
            sk->add_connection(sock,
                               local_addr.sin_addr,
                               remote_iface);
        } catch (std::runtime_error& e) {
            dbgprintf("Failed to add connection: %s\n", e.what());
        }
    }
}

void
ListenerThread::Finish()
{
    {
        PthreadScopedLock lock(&sk->scheduling_state_lock);
        sk->listener_thread = NULL;
        pthread_cond_signal(&sk->scheduling_state_cv);
    }

    dbgprintf("Exiting.\n");

    // nobody will pthread_join to me now, so detach
    //  to make sure the memory gets reclaimed
    //detach();

    delete this; // the last thing that will ever be done with this
}
<commit_msg>Trying to narrow down where the bw/rtt numbers are getting dropped on CSockets at the acceptor.<commit_after>#include <sys/types.h>
#include <sys/socket.h>
#include <unistd.h>
#include <string.h>
#include "cmm_internal_listener.h"
#include "cmm_socket.private.h"
#include "csocket_mapping.h"
#include "debug.h"
#include <netinet/in.h>
#include <arpa/inet.h>

#define INTERNAL_LISTEN_PORT 42424

ListenerThread::ListenerThread(CMMSocketImpl *sk_)
    : sk(sk_)
{
    struct sockaddr_in bind_addr;
    memset(&bind_addr, 0, sizeof(bind_addr));
    bind_addr.sin_addr.s_addr = INADDR_ANY;
    bind_addr.sin_port = htons(INTERNAL_LISTEN_PORT);

    listener_sock = socket(PF_INET, SOCK_STREAM, 0);
    if (listener_sock < 0) {
        throw -1;
    }

    int on = 1;
    int rc = setsockopt(listener_sock, SOL_SOCKET, SO_REUSEADDR,
                        (char *) &on, sizeof(on));
    if (rc < 0) {
        dbgprintf("Cannot reuse socket address\n");
    }

    do {
	rc = bind(listener_sock,
		  (struct sockaddr *)&bind_addr, sizeof(bind_addr));
	if (rc < 0) {
            //if (bind_addr.sin_port == htons(INTERNAL_LISTEN_PORT)) {
            bind_addr.sin_port = htons(ntohs(bind_addr.sin_port) + 1);
            //} else {
            //break;
            //}
	}
    } while (rc < 0);

    if (rc < 0) {
	perror("bind");
	dbgprintf("Listener failed to bind!\n");
	close(listener_sock);
	throw rc;
    }
    dbgprintf("Listener bound to port %d\n", ntohs(bind_addr.sin_port));

    socklen_t addrlen = sizeof(bind_addr);
    rc = getsockname(listener_sock,
                     (struct sockaddr *)&bind_addr, &addrlen);
    if (rc < 0) {
        perror("getsockname");
	dbgprintf("Couldn't get local listener sockaddr!\n");
        close(listener_sock);
        throw rc;
    }
    listen_port = bind_addr.sin_port;
    rc = listen(listener_sock, 5);
    if (rc < 0) {
        close(listener_sock);
        throw rc;
    }
    dbgprintf("Internal socket listener listening up on port %d\n",
              ntohs(listen_port));
}

void
ListenerThread::stop()
{
    dbgprintf("Shutting down listener %d (port %d)\n",
              listener_sock, ntohs(listen_port));
    shutdown(listener_sock, SHUT_RDWR);
    //stop();
    //join();
    //close(listener_sock);
}

in_port_t
ListenerThread::port() const
{
    return listen_port;
}

void
ListenerThread::Run()
{
    char name[MAX_NAME_LEN+1];
    memset(name, 0, MAX_NAME_LEN+1);
    snprintf(name, MAX_NAME_LEN, "Listener %d", listener_sock);
    set_thread_name(name);

    // we never join to this thread; we synchronize with its death
    // with a condition variable.
    detach();

    while (1) {
        fd_set readfds;
        FD_ZERO(&readfds);
        FD_SET(listener_sock, &readfds);
        int rc = select(listener_sock + 1, &readfds, NULL, NULL, NULL);
	if (rc < 0) {
	    if (errno == EINTR) {
		continue;
	    } else {
                close(listener_sock);
                //dbgprintf("Exiting.\n");
		return;
	    }
	}

        struct sockaddr_in remote_addr;
        socklen_t addrlen = sizeof(remote_addr);
        int sock = accept(listener_sock,
                          (struct sockaddr *)&remote_addr, &addrlen);
        if (sock < 0) {
            dbgprintf("Listener socket shutdown, listener thread exiting,"
                      " errno=%d\n",errno);
	    close(listener_sock);
            //throw std::runtime_error("Socket error");
            //dbgprintf("Exiting.\n");
            return;
        }

        struct sockaddr_in local_addr;
        rc = getsockname(sock,
                         (struct sockaddr *)&local_addr, &addrlen);
        if (rc < 0) {
            perror("getsockname");
            close(sock);
            dbgprintf("Error getting local socket address\n");
            continue;
        }

        dbgprintf("Remote host %s is connecting ",
                  inet_ntoa(remote_addr.sin_addr));
        dbgprintf_plain("to local address %s\n",
                  inet_ntoa(local_addr.sin_addr));
        struct net_interface dummy;
        if (!sk->csock_map->get_local_iface_by_addr(local_addr.sin_addr, dummy)) {
            dbgprintf("%s: network should be down.  ",
                      inet_ntoa(local_addr.sin_addr));
            dbgprintf_plain("%s, go away.\n",
                            inet_ntoa(remote_addr.sin_addr));
            close(sock);
            continue;
        }

        struct CMMSocketControlHdr hdr;
        rc = recv(sock, &hdr, sizeof(hdr), MSG_WAITALL);
        if (rc != sizeof(hdr)) {
            perror("recv");
            close(sock);
            dbgprintf("error receiving new_interface data\n");
            continue;
        }

        if (ntohs(hdr.type) != CMM_CONTROL_MSG_NEW_INTERFACE) {
            dbgprintf("Expected new-interface message on "
                      "connection start;\n   Got %s\n",
                      hdr.describe().c_str());
            close(sock);
            continue;
        }

        struct net_interface remote_iface = { hdr.op.new_interface.ip_addr,
                                              ntohl(hdr.op.new_interface.labels),
                                              ntohl(hdr.op.new_interface.bandwidth),
                                              ntohl(hdr.op.new_interface.RTT)};

        struct sockaddr_in true_remote_addr;
        memcpy(&true_remote_addr.sin_addr, &hdr.op.new_interface.ip_addr,
               sizeof(struct in_addr));
        dbgprintf("Adding connection %d from %s bw %lu RTT %lu ",
                  sock, inet_ntoa(true_remote_addr.sin_addr),
                  remote_iface.bandwidth, remote_iface.RTT);
        dbgprintf_plain("(peername %s)\n",
                        inet_ntoa(remote_addr.sin_addr));

        try {
            sk->add_connection(sock,
                               local_addr.sin_addr,
                               remote_iface);
        } catch (std::runtime_error& e) {
            dbgprintf("Failed to add connection: %s\n", e.what());
        }
    }
}

void
ListenerThread::Finish()
{
    {
        PthreadScopedLock lock(&sk->scheduling_state_lock);
        sk->listener_thread = NULL;
        pthread_cond_signal(&sk->scheduling_state_cv);
    }

    dbgprintf("Exiting.\n");

    // nobody will pthread_join to me now, so detach
    //  to make sure the memory gets reclaimed
    //detach();

    delete this; // the last thing that will ever be done with this
}
<|endoftext|>


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

#include "chrome/browser/component_updater/flash_component_installer.h"

#include <string.h>

#include <vector>

#include "base/base_paths.h"
#include "base/bind.h"
#include "base/compiler_specific.h"
#include "base/file_path.h"
#include "base/file_util.h"
#include "base/logging.h"
#include "base/path_service.h"
#include "base/string_split.h"
#include "base/string_util.h"
#include "base/stringprintf.h"
#include "base/values.h"
#include "base/version.h"
#include "build/build_config.h"
#include "chrome/browser/component_updater/component_updater_service.h"
#include "chrome/browser/component_updater/pepper_flash_field_trial.h"
#include "chrome/browser/plugin_prefs.h"
#include "chrome/common/chrome_constants.h"
#include "chrome/common/chrome_paths.h"
#include "chrome/installer/util/browser_distribution.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/plugin_service.h"
#include "content/public/common/pepper_plugin_info.h"
#include "ppapi/c/private/ppb_pdf.h"
#include "webkit/plugins/plugin_constants.h"
#include "webkit/plugins/ppapi/plugin_module.h"

using content::BrowserThread;
using content::PluginService;

namespace {

// CRX hash. The extension id is: mimojjlkmoijpicakmndhoigimigcmbb.
const uint8 sha2_hash[] = {0xc8, 0xce, 0x99, 0xba, 0xce, 0x89, 0xf8, 0x20,
                           0xac, 0xd3, 0x7e, 0x86, 0x8c, 0x86, 0x2c, 0x11,
                           0xb9, 0x40, 0xc5, 0x55, 0xaf, 0x08, 0x63, 0x70,
                           0x54, 0xf9, 0x56, 0xd3, 0xe7, 0x88, 0xba, 0x8c};

// File name of the Pepper Flash component manifest on different platforms.
const char kPepperFlashManifestName[] = "Flapper";

// Name of the Pepper Flash OS in the component manifest.
const char kPepperFlashOperatingSystem[] =
#if defined(OS_MACOSX)
    "mac";
#elif defined(OS_WIN)
    "win";
#else  // OS_LINUX, etc. TODO(viettrungluu): Separate out Chrome OS and Android?
    "linux";
#endif

// Name of the Pepper Flash architecture in the component manifest.
const char kPepperFlashArch[] =
#if defined(ARCH_CPU_X86)
    "ia32";
#elif defined(ARCH_CPU_X86_64)
    "x64";
#else  // TODO(viettrungluu): Support an ARM check?
    "???";
#endif

// The Pepper Flash plugins are in a directory with this name.
const FilePath::CharType kPepperFlashBaseDirectory[] =
    FILE_PATH_LITERAL("PepperFlash");

// If we don't have a Pepper Flash component, this is the version we claim.
const char kNullVersion[] = "0.0.0.0";

// True if Pepper Flash should be enabled by default. Aura builds for any OS
// and part of Windows canary have it enabled by default.
bool IsPepperFlashEnabledByDefault() {
#if defined(USE_AURA)
  return true;
#elif !defined(OS_WIN)
  return false;
#else
  if (!PepperFlashFieldTrial::InEnableByDefaultGroup())
    return false;

  BrowserDistribution* dist = BrowserDistribution::GetDistribution();
  if (!dist)
    return false;
  string16 channel;
  if (!dist->GetChromeChannel(&channel))
    return false;
  return (channel == L"canary");
#endif
}

// The base directory on Windows looks like:
// <profile>\AppData\Local\Google\Chrome\User Data\PepperFlash\.
FilePath GetPepperFlashBaseDirectory() {
  FilePath result;
  PathService::Get(chrome::DIR_USER_DATA, &result);
  return result.Append(kPepperFlashBaseDirectory);
}

// Pepper Flash plugins have the version encoded in the path itself
// so we need to enumerate the directories to find the full path.
// On success, |latest_dir| returns something like:
// <profile>\AppData\Local\Google\Chrome\User Data\PepperFlash\10.3.44.555\.
// |latest_version| returns the corresponding version number. |older_dirs|
// returns directories of all older versions.
bool GetPepperFlashDirectory(FilePath* latest_dir,
                             Version* latest_version,
                             std::vector<FilePath>* older_dirs) {
  FilePath base_dir = GetPepperFlashBaseDirectory();
  bool found = false;
  file_util::FileEnumerator
      file_enumerator(base_dir, false, file_util::FileEnumerator::DIRECTORIES);
  for (FilePath path = file_enumerator.Next(); !path.value().empty();
       path = file_enumerator.Next()) {
    Version version(path.BaseName().MaybeAsASCII());
    if (!version.IsValid())
      continue;
    if (found) {
      if (version.CompareTo(*latest_version) > 0) {
        older_dirs->push_back(*latest_dir);
        *latest_dir = path;
        *latest_version = version;
      } else {
        older_dirs->push_back(path);
      }
    } else {
      *latest_dir = path;
      *latest_version = version;
      found = true;
    }
  }
  return found;
}

// Returns true if the Pepper |interface_name| is implemented  by this browser.
// It does not check if the interface is proxied.
bool SupportsPepperInterface(const char* interface_name) {
  static webkit::ppapi::PluginModule::GetInterfaceFunc get_itf =
      webkit::ppapi::PluginModule::GetLocalGetInterfaceFunc();
  if (get_itf(interface_name))
    return true;
  // It might be that flapper is using as a temporary hack the PDF interface
  // so we need to check for that as well. TODO(cpu): make this more sane.
  return (strcmp(interface_name, PPB_PDF_INTERFACE) == 0);
}

bool MakePepperFlashPluginInfo(const FilePath& flash_path,
                               const Version& flash_version,
                               bool out_of_process,
                               content::PepperPluginInfo* plugin_info) {
  if (!flash_version.IsValid())
    return false;
  const std::vector<uint16> ver_nums = flash_version.components();
  if (ver_nums.size() < 3)
    return false;

  plugin_info->is_internal = false;
  plugin_info->is_out_of_process = out_of_process;
  plugin_info->path = flash_path;
  plugin_info->name = kFlashPluginName;

  // The description is like "Shockwave Flash 10.2 r154".
  plugin_info->description = StringPrintf("%s %d.%d r%d",
      kFlashPluginName, ver_nums[0], ver_nums[1], ver_nums[2]);

  plugin_info->version = flash_version.GetString();

  webkit::WebPluginMimeType swf_mime_type(kFlashPluginSwfMimeType,
                                          kFlashPluginSwfExtension,
                                          kFlashPluginName);
  plugin_info->mime_types.push_back(swf_mime_type);
  webkit::WebPluginMimeType spl_mime_type(kFlashPluginSplMimeType,
                                          kFlashPluginSplExtension,
                                          kFlashPluginName);
  plugin_info->mime_types.push_back(spl_mime_type);
  return true;
}

// If it is a |fresh_install| we enable or disable it by default in some
// configurations. See IsPepperFlashEnabledByDefault() for more information.
void RegisterPepperFlashWithChrome(const FilePath& path,
                                   const Version& version,
                                   bool fresh_install) {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
  content::PepperPluginInfo plugin_info;
  if (!MakePepperFlashPluginInfo(path, version, true, &plugin_info))
    return;
  bool enable_by_default = IsPepperFlashEnabledByDefault();
  if (fresh_install)
    PluginPrefs::EnablePluginGlobally(enable_by_default, plugin_info.path,
                                      base::Bind(&base::DoNothing));

  bool add_to_front = enable_by_default;
  PluginService::GetInstance()->RegisterInternalPlugin(
      plugin_info.ToWebPluginInfo(), add_to_front);
  PluginService::GetInstance()->RefreshPlugins();
}

// Returns true if this browser implements one of the interfaces given in
// |interface_string|, which is a '|'-separated string of interface names.
bool CheckPepperFlashInterfaceString(const std::string& interface_string) {
  std::vector<std::string> interface_names;
  base::SplitString(interface_string, '|', &interface_names);
  for (size_t i = 0; i < interface_names.size(); i++) {
    if (SupportsPepperInterface(interface_names[i].c_str()))
      return true;
  }
  return false;
}

// Returns true if this browser implements all the interfaces that Flash
// specifies in its component installer manifest.
bool CheckPepperFlashInterfaces(base::DictionaryValue* manifest) {
  base::ListValue* interface_list = NULL;

  // We don't *require* an interface list, apparently.
  if (!manifest->GetList("x-ppapi-required-interfaces", &interface_list))
    return true;

  for (size_t i = 0; i < interface_list->GetSize(); i++) {
    std::string interface_string;
    if (!interface_list->GetString(i, &interface_string))
      return false;
    if (!CheckPepperFlashInterfaceString(interface_string))
      return false;
  }

  return true;
}

}  // namespace

class PepperFlashComponentInstaller : public ComponentInstaller {
 public:
  explicit PepperFlashComponentInstaller(const Version& version);

  virtual ~PepperFlashComponentInstaller() {}

  virtual void OnUpdateError(int error) OVERRIDE;

  virtual bool Install(base::DictionaryValue* manifest,
                       const FilePath& unpack_path) OVERRIDE;

 private:
  Version current_version_;
};

PepperFlashComponentInstaller::PepperFlashComponentInstaller(
    const Version& version) : current_version_(version) {
  DCHECK(version.IsValid());
}

void PepperFlashComponentInstaller::OnUpdateError(int error) {
  NOTREACHED() << "Pepper Flash update error: " << error;
}

bool PepperFlashComponentInstaller::Install(base::DictionaryValue* manifest,
                                            const FilePath& unpack_path) {
  Version version;
  if (!CheckPepperFlashManifest(manifest, &version))
    return false;
  if (current_version_.CompareTo(version) > 0)
    return false;
  if (!file_util::PathExists(unpack_path.Append(
          chrome::kPepperFlashPluginFilename)))
    return false;
  // Passed the basic tests. Time to install it.
  FilePath path =
      GetPepperFlashBaseDirectory().AppendASCII(version.GetString());
  if (file_util::PathExists(path))
    return false;
  if (!file_util::Move(unpack_path, path))
    return false;
  // Installation is done. Now tell the rest of chrome. Both the path service
  // and to the plugin service.
  current_version_ = version;
  PathService::Override(chrome::DIR_PEPPER_FLASH_PLUGIN, path);
  path = path.Append(chrome::kPepperFlashPluginFilename);
  BrowserThread::PostTask(
      BrowserThread::UI, FROM_HERE,
      base::Bind(&RegisterPepperFlashWithChrome, path, version, true));
  return true;
}

bool CheckPepperFlashManifest(base::DictionaryValue* manifest,
                              Version* version_out) {
  std::string name;
  manifest->GetStringASCII("name", &name);
  // TODO(viettrungluu): Support WinFlapper for now, while we change the format
  // of the manifest. (Should be safe to remove checks for "WinFlapper" in, say,
  // Nov. 2011.)  crbug.com/98458
  if (name != kPepperFlashManifestName && name != "WinFlapper")
    return false;

  std::string proposed_version;
  manifest->GetStringASCII("version", &proposed_version);
  Version version(proposed_version.c_str());
  if (!version.IsValid())
    return false;

  if (!CheckPepperFlashInterfaces(manifest))
    return false;

  // TODO(viettrungluu): See above TODO.
  if (name == "WinFlapper") {
    *version_out = version;
    return true;
  }

  std::string os;
  manifest->GetStringASCII("x-ppapi-os", &os);
  if (os != kPepperFlashOperatingSystem)
    return false;

  std::string arch;
  manifest->GetStringASCII("x-ppapi-arch", &arch);
  if (arch != kPepperFlashArch)
    return false;

  *version_out = version;
  return true;
}

namespace {

void FinishPepperFlashUpdateRegistration(ComponentUpdateService* cus,
                                         const Version& version) {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
  CrxComponent pepflash;
  pepflash.name = "pepper_flash";
  pepflash.installer = new PepperFlashComponentInstaller(version);
  pepflash.version = version;
  pepflash.pk_hash.assign(sha2_hash, &sha2_hash[sizeof(sha2_hash)]);
  if (cus->RegisterComponent(pepflash) != ComponentUpdateService::kOk) {
    NOTREACHED() << "Pepper Flash component registration failed.";
  }
}

void StartPepperFlashUpdateRegistration(ComponentUpdateService* cus) {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
  FilePath path = GetPepperFlashBaseDirectory();
  if (!file_util::PathExists(path)) {
    if (!file_util::CreateDirectory(path)) {
      NOTREACHED() << "Could not create Pepper Flash directory.";
      return;
    }
  }

  Version version(kNullVersion);
  std::vector<FilePath> older_dirs;
  if (GetPepperFlashDirectory(&path, &version, &older_dirs)) {
    path = path.Append(chrome::kPepperFlashPluginFilename);
    if (file_util::PathExists(path)) {
      BrowserThread::PostTask(
          BrowserThread::UI, FROM_HERE,
          base::Bind(&RegisterPepperFlashWithChrome, path, version, false));
    } else {
      version = Version(kNullVersion);
    }
  }

  BrowserThread::PostTask(
      BrowserThread::UI, FROM_HERE,
      base::Bind(&FinishPepperFlashUpdateRegistration, cus, version));

  // Remove older versions of Pepper Flash.
  for (std::vector<FilePath>::iterator iter = older_dirs.begin();
       iter != older_dirs.end(); ++iter) {
    file_util::Delete(*iter, true);
  }
}

}  // namespace

void RegisterPepperFlashComponent(ComponentUpdateService* cus) {
#if defined(GOOGLE_CHROME_BUILD)
  BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE,
                          base::Bind(&StartPepperFlashUpdateRegistration, cus));
#endif
}
<commit_msg>Enable flapper by default on window 8 metro mode<commit_after>// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/browser/component_updater/flash_component_installer.h"

#include <string.h>

#include <vector>

#include "base/base_paths.h"
#include "base/bind.h"
#include "base/compiler_specific.h"
#include "base/file_path.h"
#include "base/file_util.h"
#include "base/logging.h"
#include "base/path_service.h"
#include "base/string_split.h"
#include "base/string_util.h"
#include "base/stringprintf.h"
#include "base/values.h"
#include "base/version.h"
#include "build/build_config.h"
#include "chrome/browser/component_updater/component_updater_service.h"
#include "chrome/browser/component_updater/pepper_flash_field_trial.h"
#include "chrome/browser/plugin_prefs.h"
#include "chrome/common/chrome_constants.h"
#include "chrome/common/chrome_paths.h"
#include "chrome/installer/util/browser_distribution.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/plugin_service.h"
#include "content/public/common/pepper_plugin_info.h"
#include "ppapi/c/private/ppb_pdf.h"
#include "webkit/plugins/plugin_constants.h"
#include "webkit/plugins/ppapi/plugin_module.h"

#if defined(OS_WIN)
#include "base/win/metro.h"
#endif

using content::BrowserThread;
using content::PluginService;

namespace {

// CRX hash. The extension id is: mimojjlkmoijpicakmndhoigimigcmbb.
const uint8 sha2_hash[] = {0xc8, 0xce, 0x99, 0xba, 0xce, 0x89, 0xf8, 0x20,
                           0xac, 0xd3, 0x7e, 0x86, 0x8c, 0x86, 0x2c, 0x11,
                           0xb9, 0x40, 0xc5, 0x55, 0xaf, 0x08, 0x63, 0x70,
                           0x54, 0xf9, 0x56, 0xd3, 0xe7, 0x88, 0xba, 0x8c};

// File name of the Pepper Flash component manifest on different platforms.
const char kPepperFlashManifestName[] = "Flapper";

// Name of the Pepper Flash OS in the component manifest.
const char kPepperFlashOperatingSystem[] =
#if defined(OS_MACOSX)
    "mac";
#elif defined(OS_WIN)
    "win";
#else  // OS_LINUX, etc. TODO(viettrungluu): Separate out Chrome OS and Android?
    "linux";
#endif

// Name of the Pepper Flash architecture in the component manifest.
const char kPepperFlashArch[] =
#if defined(ARCH_CPU_X86)
    "ia32";
#elif defined(ARCH_CPU_X86_64)
    "x64";
#else  // TODO(viettrungluu): Support an ARM check?
    "???";
#endif

// The Pepper Flash plugins are in a directory with this name.
const FilePath::CharType kPepperFlashBaseDirectory[] =
    FILE_PATH_LITERAL("PepperFlash");

// If we don't have a Pepper Flash component, this is the version we claim.
const char kNullVersion[] = "0.0.0.0";

// True if Pepper Flash should be enabled by default. Aura builds for any OS
// Windows 8 metro mode and part of Windows canary have it enabled by default.
bool IsPepperFlashEnabledByDefault() {
#if defined(USE_AURA)
  return true;
#elif !defined(OS_WIN)
  return false;
#else
  if (base::win::GetMetroModule())
    return true;
  if (!PepperFlashFieldTrial::InEnableByDefaultGroup())
    return false;

  BrowserDistribution* dist = BrowserDistribution::GetDistribution();
  if (!dist)
    return false;
  string16 channel;
  if (!dist->GetChromeChannel(&channel))
    return false;
  return (channel == L"canary");
#endif
}

// The base directory on Windows looks like:
// <profile>\AppData\Local\Google\Chrome\User Data\PepperFlash\.
FilePath GetPepperFlashBaseDirectory() {
  FilePath result;
  PathService::Get(chrome::DIR_USER_DATA, &result);
  return result.Append(kPepperFlashBaseDirectory);
}

// Pepper Flash plugins have the version encoded in the path itself
// so we need to enumerate the directories to find the full path.
// On success, |latest_dir| returns something like:
// <profile>\AppData\Local\Google\Chrome\User Data\PepperFlash\10.3.44.555\.
// |latest_version| returns the corresponding version number. |older_dirs|
// returns directories of all older versions.
bool GetPepperFlashDirectory(FilePath* latest_dir,
                             Version* latest_version,
                             std::vector<FilePath>* older_dirs) {
  FilePath base_dir = GetPepperFlashBaseDirectory();
  bool found = false;
  file_util::FileEnumerator
      file_enumerator(base_dir, false, file_util::FileEnumerator::DIRECTORIES);
  for (FilePath path = file_enumerator.Next(); !path.value().empty();
       path = file_enumerator.Next()) {
    Version version(path.BaseName().MaybeAsASCII());
    if (!version.IsValid())
      continue;
    if (found) {
      if (version.CompareTo(*latest_version) > 0) {
        older_dirs->push_back(*latest_dir);
        *latest_dir = path;
        *latest_version = version;
      } else {
        older_dirs->push_back(path);
      }
    } else {
      *latest_dir = path;
      *latest_version = version;
      found = true;
    }
  }
  return found;
}

// Returns true if the Pepper |interface_name| is implemented  by this browser.
// It does not check if the interface is proxied.
bool SupportsPepperInterface(const char* interface_name) {
  static webkit::ppapi::PluginModule::GetInterfaceFunc get_itf =
      webkit::ppapi::PluginModule::GetLocalGetInterfaceFunc();
  if (get_itf(interface_name))
    return true;
  // It might be that flapper is using as a temporary hack the PDF interface
  // so we need to check for that as well. TODO(cpu): make this more sane.
  return (strcmp(interface_name, PPB_PDF_INTERFACE) == 0);
}

bool MakePepperFlashPluginInfo(const FilePath& flash_path,
                               const Version& flash_version,
                               bool out_of_process,
                               content::PepperPluginInfo* plugin_info) {
  if (!flash_version.IsValid())
    return false;
  const std::vector<uint16> ver_nums = flash_version.components();
  if (ver_nums.size() < 3)
    return false;

  plugin_info->is_internal = false;
  plugin_info->is_out_of_process = out_of_process;
  plugin_info->path = flash_path;
  plugin_info->name = kFlashPluginName;

  // The description is like "Shockwave Flash 10.2 r154".
  plugin_info->description = StringPrintf("%s %d.%d r%d",
      kFlashPluginName, ver_nums[0], ver_nums[1], ver_nums[2]);

  plugin_info->version = flash_version.GetString();

  webkit::WebPluginMimeType swf_mime_type(kFlashPluginSwfMimeType,
                                          kFlashPluginSwfExtension,
                                          kFlashPluginName);
  plugin_info->mime_types.push_back(swf_mime_type);
  webkit::WebPluginMimeType spl_mime_type(kFlashPluginSplMimeType,
                                          kFlashPluginSplExtension,
                                          kFlashPluginName);
  plugin_info->mime_types.push_back(spl_mime_type);
  return true;
}

// If it is a |fresh_install| we enable or disable it by default in some
// configurations. See IsPepperFlashEnabledByDefault() for more information.
void RegisterPepperFlashWithChrome(const FilePath& path,
                                   const Version& version,
                                   bool fresh_install) {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
  content::PepperPluginInfo plugin_info;
  if (!MakePepperFlashPluginInfo(path, version, true, &plugin_info))
    return;
  bool enable_by_default = IsPepperFlashEnabledByDefault();
  if (fresh_install)
    PluginPrefs::EnablePluginGlobally(enable_by_default, plugin_info.path,
                                      base::Bind(&base::DoNothing));

  bool add_to_front = enable_by_default;
  PluginService::GetInstance()->RegisterInternalPlugin(
      plugin_info.ToWebPluginInfo(), add_to_front);
  PluginService::GetInstance()->RefreshPlugins();
}

// Returns true if this browser implements one of the interfaces given in
// |interface_string|, which is a '|'-separated string of interface names.
bool CheckPepperFlashInterfaceString(const std::string& interface_string) {
  std::vector<std::string> interface_names;
  base::SplitString(interface_string, '|', &interface_names);
  for (size_t i = 0; i < interface_names.size(); i++) {
    if (SupportsPepperInterface(interface_names[i].c_str()))
      return true;
  }
  return false;
}

// Returns true if this browser implements all the interfaces that Flash
// specifies in its component installer manifest.
bool CheckPepperFlashInterfaces(base::DictionaryValue* manifest) {
  base::ListValue* interface_list = NULL;

  // We don't *require* an interface list, apparently.
  if (!manifest->GetList("x-ppapi-required-interfaces", &interface_list))
    return true;

  for (size_t i = 0; i < interface_list->GetSize(); i++) {
    std::string interface_string;
    if (!interface_list->GetString(i, &interface_string))
      return false;
    if (!CheckPepperFlashInterfaceString(interface_string))
      return false;
  }

  return true;
}

}  // namespace

class PepperFlashComponentInstaller : public ComponentInstaller {
 public:
  explicit PepperFlashComponentInstaller(const Version& version);

  virtual ~PepperFlashComponentInstaller() {}

  virtual void OnUpdateError(int error) OVERRIDE;

  virtual bool Install(base::DictionaryValue* manifest,
                       const FilePath& unpack_path) OVERRIDE;

 private:
  Version current_version_;
};

PepperFlashComponentInstaller::PepperFlashComponentInstaller(
    const Version& version) : current_version_(version) {
  DCHECK(version.IsValid());
}

void PepperFlashComponentInstaller::OnUpdateError(int error) {
  NOTREACHED() << "Pepper Flash update error: " << error;
}

bool PepperFlashComponentInstaller::Install(base::DictionaryValue* manifest,
                                            const FilePath& unpack_path) {
  Version version;
  if (!CheckPepperFlashManifest(manifest, &version))
    return false;
  if (current_version_.CompareTo(version) > 0)
    return false;
  if (!file_util::PathExists(unpack_path.Append(
          chrome::kPepperFlashPluginFilename)))
    return false;
  // Passed the basic tests. Time to install it.
  FilePath path =
      GetPepperFlashBaseDirectory().AppendASCII(version.GetString());
  if (file_util::PathExists(path))
    return false;
  if (!file_util::Move(unpack_path, path))
    return false;
  // Installation is done. Now tell the rest of chrome. Both the path service
  // and to the plugin service.
  current_version_ = version;
  PathService::Override(chrome::DIR_PEPPER_FLASH_PLUGIN, path);
  path = path.Append(chrome::kPepperFlashPluginFilename);
  BrowserThread::PostTask(
      BrowserThread::UI, FROM_HERE,
      base::Bind(&RegisterPepperFlashWithChrome, path, version, true));
  return true;
}

bool CheckPepperFlashManifest(base::DictionaryValue* manifest,
                              Version* version_out) {
  std::string name;
  manifest->GetStringASCII("name", &name);
  // TODO(viettrungluu): Support WinFlapper for now, while we change the format
  // of the manifest. (Should be safe to remove checks for "WinFlapper" in, say,
  // Nov. 2011.)  crbug.com/98458
  if (name != kPepperFlashManifestName && name != "WinFlapper")
    return false;

  std::string proposed_version;
  manifest->GetStringASCII("version", &proposed_version);
  Version version(proposed_version.c_str());
  if (!version.IsValid())
    return false;

  if (!CheckPepperFlashInterfaces(manifest))
    return false;

  // TODO(viettrungluu): See above TODO.
  if (name == "WinFlapper") {
    *version_out = version;
    return true;
  }

  std::string os;
  manifest->GetStringASCII("x-ppapi-os", &os);
  if (os != kPepperFlashOperatingSystem)
    return false;

  std::string arch;
  manifest->GetStringASCII("x-ppapi-arch", &arch);
  if (arch != kPepperFlashArch)
    return false;

  *version_out = version;
  return true;
}

namespace {

void FinishPepperFlashUpdateRegistration(ComponentUpdateService* cus,
                                         const Version& version) {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
  CrxComponent pepflash;
  pepflash.name = "pepper_flash";
  pepflash.installer = new PepperFlashComponentInstaller(version);
  pepflash.version = version;
  pepflash.pk_hash.assign(sha2_hash, &sha2_hash[sizeof(sha2_hash)]);
  if (cus->RegisterComponent(pepflash) != ComponentUpdateService::kOk) {
    NOTREACHED() << "Pepper Flash component registration failed.";
  }
}

void StartPepperFlashUpdateRegistration(ComponentUpdateService* cus) {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
  FilePath path = GetPepperFlashBaseDirectory();
  if (!file_util::PathExists(path)) {
    if (!file_util::CreateDirectory(path)) {
      NOTREACHED() << "Could not create Pepper Flash directory.";
      return;
    }
  }

  Version version(kNullVersion);
  std::vector<FilePath> older_dirs;
  if (GetPepperFlashDirectory(&path, &version, &older_dirs)) {
    path = path.Append(chrome::kPepperFlashPluginFilename);
    if (file_util::PathExists(path)) {
      BrowserThread::PostTask(
          BrowserThread::UI, FROM_HERE,
          base::Bind(&RegisterPepperFlashWithChrome, path, version, false));
    } else {
      version = Version(kNullVersion);
    }
  }

  BrowserThread::PostTask(
      BrowserThread::UI, FROM_HERE,
      base::Bind(&FinishPepperFlashUpdateRegistration, cus, version));

  // Remove older versions of Pepper Flash.
  for (std::vector<FilePath>::iterator iter = older_dirs.begin();
       iter != older_dirs.end(); ++iter) {
    file_util::Delete(*iter, true);
  }
}

}  // namespace

void RegisterPepperFlashComponent(ComponentUpdateService* cus) {
#if defined(GOOGLE_CHROME_BUILD)
  BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE,
                          base::Bind(&StartPepperFlashUpdateRegistration, cus));
#endif
}
<|endoftext|>


<commit_before>/*
    This file is part of Magnum.

    Original authors — credit is appreciated but not required:

        2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019 —
            Vladimír Vondruš <mosra@centrum.cz>

    This is free and unencumbered software released into the public domain.

    Anyone is free to copy, modify, publish, use, compile, sell, or distribute
    this software, either in source code form or as a compiled binary, for any
    purpose, commercial or non-commercial, and by any means.

    In jurisdictions that recognize copyright laws, the author or authors of
    this software dedicate any and all copyright interest in the software to
    the public domain. We make this dedication for the benefit of the public
    at large and to the detriment of our heirs and successors. We intend this
    dedication to be an overt act of relinquishment in perpetuity of all
    present and future rights to this software under copyright law.

    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 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 <GL/glew.h>
#include <Magnum/Math/Color.h>
#include <Magnum/Platform/Sdl2Application.h>

/* Integrate with Magnum a bit */
#define SOKOL_ASSERT(c) CORRADE_INTERNAL_ASSERT(c)
#define SOKOL_LOG(c) do { Corrade::Utility::Debug{} << c; } while(0)
#define SOKOL_UNREACHABLE CORRADE_ASSERT_UNREACHABLE()
#define SOKOL_GLCORE33
#include "sokol_gfx.h"

namespace Magnum { namespace Examples {

using namespace Math::Literals;

class TriangleSokolExample: public Platform::Application {
    public:
        explicit TriangleSokolExample(const Arguments& arguments);
        ~TriangleSokolExample();

    private:
        void drawEvent() override;

        SDL_GLContext _context;

        sg_buffer _vertices;
        sg_shader _shader;
        sg_pipeline _pipeline;
};

constexpr Vector2i Size{800, 600};

TriangleSokolExample::TriangleSokolExample(const Arguments& arguments):
    Platform::Application{arguments, Configuration{}
        .setTitle("Magnum Triangle using sokol_gfx")
        .setSize(Size)
        .setWindowFlags(Configuration::WindowFlag::Contextless)}
{
    /* Initialize context using toolkit-specific functionality. When the
       Magnum::GL library is not used, this is left completely to the user ---
       some renderers may have their own routines, some expect the user to do
       the initialization. OpenGL is used only as an example, could be anything
       else, Vulkan, D3D, Metal. */
    SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
    SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 24);
    SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3);
    SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 3);
    SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE);
    _context = SDL_GL_CreateContext(window());
    glewInit();

    /* Setup sokol_gfx */
    {
        sg_desc desc{};
        sg_setup(&desc);
    }

    /* A vertex buffer */
    {
        const struct TriangleVertex {
            Vector2 position;
            Color3 color;
        } data[]{
            {{-0.5f, -0.5f}, 0xff0000_rgbf}, /* Left vertex, red color */
            {{ 0.5f, -0.5f}, 0x00ff00_rgbf}, /* Right vertex, green color */
            {{ 0.0f,  0.5f}, 0x0000ff_rgbf}  /* Top vertex, blue color */
        };
        sg_buffer_desc desc{};
        desc.content = data;
        desc.size = sizeof(data);
        _vertices = sg_make_buffer(&desc);
    }

    /* A shader */
    {
        sg_shader_desc desc{};
        desc.vs.source = CORRADE_LINE_STRING "\n" R"GLSL(
#version 330
in vec4 position;
in vec4 color;
out vec4 interpolatedColor;

void main() {
    gl_Position = position;
    interpolatedColor = color;
}
)GLSL";
        desc.fs.source = CORRADE_LINE_STRING "\n" R"GLSL(
#version 330
in vec4 interpolatedColor;
out vec4 fragmentColor;

void main() {
    fragmentColor = interpolatedColor;
}
)GLSL";
        _shader = sg_make_shader(&desc);
    }

    /* A pipeline state object */
    {
        sg_pipeline_desc desc{};
        desc.shader = _shader;
        desc.layout.attrs[0].name = "position";
        desc.layout.attrs[0].format = SG_VERTEXFORMAT_FLOAT2;
        desc.layout.attrs[1].name = "color";
        desc.layout.attrs[1].format = SG_VERTEXFORMAT_FLOAT3;
        _pipeline = sg_make_pipeline(&desc);
    }
}

TriangleSokolExample::~TriangleSokolExample() {
    sg_shutdown();

    SDL_GL_DeleteContext(_context);
}

void TriangleSokolExample::drawEvent() {
    /* Clear the framebuffer */
    {
        sg_pass_action action{};
        action.colors[0].action = SG_ACTION_CLEAR;
        Color4::from(action.colors[0].val) = 0x1f1f1f_rgbf;
        sg_begin_default_pass(&action, Size.x(), Size.y());
    }

    /* Draw the triangle */
    {
        sg_draw_state state{};
        state.pipeline = _pipeline;
        state.vertex_buffers[0] = _vertices;
        sg_apply_draw_state(&state);
        sg_draw(0, 3, 1);
    }

    sg_end_pass();
    sg_commit();

    swapBuffers();
}

}}

MAGNUM_APPLICATION_MAIN(Magnum::Examples::TriangleSokolExample)
<commit_msg>triangle-sokol: make it actually finally work.<commit_after>/*
    This file is part of Magnum.

    Original authors — credit is appreciated but not required:

        2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019 —
            Vladimír Vondruš <mosra@centrum.cz>

    This is free and unencumbered software released into the public domain.

    Anyone is free to copy, modify, publish, use, compile, sell, or distribute
    this software, either in source code form or as a compiled binary, for any
    purpose, commercial or non-commercial, and by any means.

    In jurisdictions that recognize copyright laws, the author or authors of
    this software dedicate any and all copyright interest in the software to
    the public domain. We make this dedication for the benefit of the public
    at large and to the detriment of our heirs and successors. We intend this
    dedication to be an overt act of relinquishment in perpetuity of all
    present and future rights to this software under copyright law.

    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 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 <GL/glew.h>
#include <Magnum/Math/Color.h>
#include <Magnum/Platform/Sdl2Application.h>

/* Integrate with Magnum a bit */
#define SOKOL_ASSERT(c) CORRADE_INTERNAL_ASSERT(c)
#define SOKOL_LOG(c) do { Corrade::Utility::Debug{} << c; } while(0)
#define SOKOL_UNREACHABLE CORRADE_ASSERT_UNREACHABLE()
#define SOKOL_GLCORE33
#include "sokol_gfx.h"

namespace Magnum { namespace Examples {

using namespace Math::Literals;

class TriangleSokolExample: public Platform::Application {
    public:
        explicit TriangleSokolExample(const Arguments& arguments);
        ~TriangleSokolExample();

    private:
        void drawEvent() override;

        SDL_GLContext _context;

        sg_buffer _vertices;
        sg_shader _shader;
        sg_pipeline _pipeline;
};

TriangleSokolExample::TriangleSokolExample(const Arguments& arguments):
    Platform::Application{arguments, Configuration{}
        .setTitle("Magnum Triangle using sokol_gfx")
        .setWindowFlags(Configuration::WindowFlag::Contextless|Configuration::WindowFlag::OpenGL)}
{
    /* Initialize context using toolkit-specific functionality. When the
       Magnum::GL library is not used, this is left completely to the user ---
       some renderers may have their own routines, some expect the user to do
       the initialization. OpenGL is used only as an example, could be anything
       else, Vulkan, D3D, Metal. */
    SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
    SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 24);
    SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3);
    SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 3);
    SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE);
    _context = SDL_GL_CreateContext(window());
    if(!_context) Fatal{} << "Can not create context:" << SDL_GetError();
    SDL_GL_MakeCurrent(window(), _context);
    glewInit();

    /* Setup sokol_gfx */
    {
        sg_desc desc{};
        sg_setup(&desc);
    }

    /* A vertex buffer */
    {
        const struct TriangleVertex {
            Vector2 position;
            Color3 color;
        } data[]{
            {{-0.5f, -0.5f}, 0xff0000_rgbf}, /* Left vertex, red color */
            {{ 0.5f, -0.5f}, 0x00ff00_rgbf}, /* Right vertex, green color */
            {{ 0.0f,  0.5f}, 0x0000ff_rgbf}  /* Top vertex, blue color */
        };
        sg_buffer_desc desc{};
        desc.content = data;
        desc.size = sizeof(data);
        _vertices = sg_make_buffer(&desc);
    }

    /* A shader */
    {
        sg_shader_desc desc{};
        desc.vs.source = "#version 330\n#line " CORRADE_LINE_STRING "\n" R"GLSL(
in vec4 position;
in vec4 color;
out vec4 interpolatedColor;

void main() {
    gl_Position = position;
    interpolatedColor = color;
}
)GLSL";
        desc.fs.source = "#version 330\n#line " CORRADE_LINE_STRING "\n" R"GLSL(
in vec4 interpolatedColor;
out vec4 fragmentColor;

void main() {
    fragmentColor = interpolatedColor;
}
)GLSL";
        _shader = sg_make_shader(&desc);
    }

    /* A pipeline state object */
    {
        sg_pipeline_desc desc{};
        desc.shader = _shader;
        desc.layout.attrs[0].name = "position";
        desc.layout.attrs[0].format = SG_VERTEXFORMAT_FLOAT2;
        desc.layout.attrs[1].name = "color";
        desc.layout.attrs[1].format = SG_VERTEXFORMAT_FLOAT3;
        _pipeline = sg_make_pipeline(&desc);
    }
}

TriangleSokolExample::~TriangleSokolExample() {
    sg_shutdown();

    SDL_GL_DeleteContext(_context);
}

void TriangleSokolExample::drawEvent() {
    /* Clear the framebuffer */
    {
        sg_pass_action action{};
        action.colors[0].action = SG_ACTION_CLEAR;
        Color4::from(action.colors[0].val) = 0x1f1f1f_rgbf;
        sg_begin_default_pass(&action, framebufferSize().x(), framebufferSize().y());
    }

    /* Draw the triangle */
    {
        sg_draw_state state{};
        state.pipeline = _pipeline;
        state.vertex_buffers[0] = _vertices;
        sg_apply_draw_state(&state);
        sg_draw(0, 3, 1);
    }

    sg_end_pass();
    sg_commit();

    swapBuffers();
}

}}

MAGNUM_APPLICATION_MAIN(Magnum::Examples::TriangleSokolExample)
<|endoftext|>


<commit_before>#ifndef __HTSLIBPP_BAMALIGNEMNT_HPP__
#define __HTSLIBPP_BAMALIGNEMNT_HPP__
#include <stdint.h>
#include <memory>
#include <cstring>
namespace BamTools {
	static std::string _mkstr(const uint8_t* what) { return std::string((const char*)what + 1); }
	struct CigarOp {

		char     Type;   //!< CIGAR operation type (MIDNSHPX=)
		uint32_t Length; //!< CIGAR operation length (number of bases)

		//! constructor
		CigarOp(const char type = '\0',
				const uint32_t& length = 0)
			: Type(type)
			, Length(length)
		{ }
	};
	const char cigar_ops_as_chars[] = { 'M', 'I', 'D', 'N', 'S', 'H', 'P', '=', 'X', 'B' };

	class BamAlignment {

		bam1_t _bam;

		template <typename Destination>
		struct _TagGetterBase
		{
			_TagGetterBase(const BamAlignment& parent, Destination& dest) : _dest(dest), _parent(parent) {}
			Destination& _dest;
			const BamAlignment& _parent;
		};

		template <typename Left, typename Right>
		struct _TagGetter : _TagGetterBase<Right>
		{
			operator bool() { return false; }

			_TagGetter(const BamAlignment& parent, Right& right) : _TagGetterBase<Right>(parent, right) {}

			template <class MakeValue>
			bool operator()(const std::string tag, MakeValue make_value)
			{
				return false;
			}
		};

		template <typename Left>
		struct _TagGetter<Left, Left> : _TagGetterBase<Left>
		{
			operator bool() { return true; }

			_TagGetter(const BamAlignment& parent, Left& right) : _TagGetterBase<Left>(parent, right){};

			template <class MakeValue>
			bool operator ()(const std::string& tag, MakeValue make_value)
			{
				const uint8_t* data = bam_aux_get(this->_parent.HtsObj(), tag.c_str());
				if(nullptr == data) return false;
				this->_dest = make_value(data);
				return true;
			}
		};

	public:

		const bam1_t* HtsObj() const
		{
			return &_bam;
		}

		bam1_t* HtsObj2()
		{
			return &_bam;
		}

		std::string Name;
		std::string Filename;
		std::vector<CigarOp> CigarData;

		void InitCigarData()
		{
			CigarData.clear();

			uint32_t *cigar = bam_get_cigar(&_bam);
			uint32_t num_cigar_elements = _bam.core.n_cigar;

			for ( uint32_t i = 0; i < num_cigar_elements; ++i )
			{
				char type = cigar_ops_as_chars[static_cast<int>(bam_cigar_op(cigar[i]))];
				uint32_t len = bam_cigar_oplen(cigar[i]);
				CigarData.push_back(CigarOp(type, len));
			}
		}

		/* TODO: fix all this dummy strings What is TagData? Not from file? */
		std::string AlignedBases, Qualities, ErrorString, TagData;
		uint32_t BlockLength;

		std::string QueryBases;

		void InitAdditionalData()
		{
			QueryBases = "";
			static const char* base2char = "=ACMGRSVTWYHKDBN";
			const uint8_t* seq = bam_get_seq(&_bam);

			for(unsigned i = 0; i < QuerySequenceLength; i ++)
			{
				char cur_base = base2char[bam_seqi(seq, i)];
				QueryBases.push_back(cur_base);
			}

			Qualities = "";

			const uint8_t* qual = bam_get_qual(&_bam);

			if(_bam.core.l_qseq == 0 || qual[0] == 0xffu)
				Qualities.resize(QuerySequenceLength, -1);
			else for(unsigned i = 0; i < QuerySequenceLength; i ++)
				Qualities.push_back((char)(33 + qual[i]));
		}

#include <BamAlignment.mapping.hpp>

		struct _SupportData {
			_QueryNameLength_t& QueryNameLength;
			_QuerySequenceLength_t& QuerySequenceLength;
			_NumCigarOperations_t& NumCigarOperations;
			uint32_t& BlockLength;
			std::string AllCharData;
			bool HasCoreOnly;  /* TODO(haohou): populate the string data */
			/* TODO(haohou): Tag2Cigar?  Real Cigar ? */
			_SupportData(BamAlignment& parent):
				QueryNameLength(parent.QueryNameLength),
				QuerySequenceLength(parent.QuerySequenceLength),
				NumCigarOperations(parent.NumCigarOperations),
				BlockLength(parent.BlockLength),
				HasCoreOnly(false)
			{
			}
		} SupportData;

		~BamAlignment()
		{
			free(_bam.data);
		}

		BamAlignment() : BlockLength(0), SupportData(*this)
		{
			memset(&_bam, 0, sizeof(_bam));
		}

		BamAlignment(const std::string& filename, const bam1_t* bam, uint32_t size = 0) :
			Name(bam_get_qname(bam)),
			Filename(filename),
			BlockLength(size),
			SupportData(*this)
		{
			bam_copy1(&_bam, bam);
			InitCigarData();
			InitAdditionalData();
		}

		BamAlignment(const BamAlignment& ba) :
			Filename(ba.Filename),
			SupportData(*this)
		{
			bam_copy1(&_bam, ba.HtsObj());
			CigarData = ba.CigarData;
			QueryBases = ba.QueryBases;
			Qualities = ba.Qualities;
			SupportData.AllCharData = ba.SupportData.AllCharData;
		}

		const BamAlignment& operator = (const BamAlignment& ba)
		{
			Name = ba.Name;
			Filename = ba.Filename;
			bam_copy1(&_bam, ba.HtsObj());
			BlockLength = ba.BlockLength;
			CigarData = ba.CigarData;
			QueryBases = ba.QueryBases;
			Qualities = ba.Qualities;
			SupportData.AllCharData = ba.SupportData.AllCharData;
			return *this;
		}

		void operator ()(const std::string filename, const bam1_t* bam, uint32_t size = 0, bool copy = true)
		{
			Filename = filename;
			Name = std::string(bam_get_qname(bam));
			BlockLength = size;
			if(copy)
				bam_copy1(&_bam, bam);
			else
			{
				free(_bam.data);
				_bam = *bam;
			}

			SupportData.AllCharData = std::string((const char*)_bam.data, _bam.l_data);

			InitCigarData();
		}

		inline bool GetAlignmentFlag(uint32_t mask) const
		{
			return _bam.core.flag & mask;
		}

		inline void SetAlignmentFlag(uint32_t mask, bool val)
		{
			if(val && !(_bam.core.flag & mask))
				_bam.core.flag |= mask;
			else if(val && (_bam.core.flag & mask))
				_bam.core.flag &= ~mask;
		}

#define FLAG_ACCESSOR(name, mask) \
		inline bool Is##name() const { return GetAlignmentFlag(mask); }; \
		inline void SetIs##name(bool val) { SetAlignmentFlag(mask, val); };

		inline bool IsMapped() const
		{
			return !(_bam.core.flag & BAM_FUNMAP);
		}

		bool IsMateMapped() const
		{
			return !(_bam.core.flag & BAM_FMUNMAP);
		}

		FLAG_ACCESSOR(FirstMate, BAM_FREAD1);
		FLAG_ACCESSOR(SecondMate, BAM_FREAD2);
		FLAG_ACCESSOR(ReverseStrand, BAM_FREVERSE);
		FLAG_ACCESSOR(MateReverseStrand, BAM_FMREVERSE);
		FLAG_ACCESSOR(ProperPair, BAM_FPROPER_PAIR);
		FLAG_ACCESSOR(Paired, BAM_FPAIRED);
		FLAG_ACCESSOR(Duplicate, BAM_FDUP);
		FLAG_ACCESSOR(FailedQC, BAM_FQCFAIL);

		int GetEndPosition(bool usePadded = false, bool closedInterval = false) const
		{
			if(usePadded || closedInterval)
			{
				fprintf(stderr, "FIXME: we current do not support the usePadded and closedInterval param");
			}

			return bam_endpos(&_bam);
		}

		template <typename T>
		bool GetTag(const std::string& tag, T& destination) const
		{

			_TagGetter<std::string, T> string_getter(*this, destination);
			if(string_getter)
				return string_getter(tag, _mkstr);
			return false;
		}

		bool HasTag(const std::string& tag) const
		{
			const uint8_t *aux_ptr = bam_aux_get(&_bam, tag.c_str());
			if ( aux_ptr == nullptr )
				return false;
			return true;
		}

		template <typename T>
		bool AddTag(const std::string& tag, const std::string& type, T data)
		{
			_TagGetter<std::string, T> string_getter(*this, data);
			if(string_getter && "Z" == type)
			{
				std::string* str = static_cast<std::string*>(&data);
				bam_aux_append(&_bam, tag.c_str(), 'Z', str->size() + 1, (uint8_t*)str->c_str());
				return true;
			}
			return false;
		}

	};
}
#endif
<commit_msg>String constructor is slow<commit_after>#ifndef __HTSLIBPP_BAMALIGNEMNT_HPP__
#define __HTSLIBPP_BAMALIGNEMNT_HPP__
#include <stdint.h>
#include <memory>
#include <cstring>
namespace BamTools {
	static std::string _mkstr(const uint8_t* what) { return std::string((const char*)what + 1); }
	struct CigarOp {

		char     Type;   //!< CIGAR operation type (MIDNSHPX=)
		uint32_t Length; //!< CIGAR operation length (number of bases)

		//! constructor
		CigarOp(const char type = '\0',
				const uint32_t& length = 0)
			: Type(type)
			, Length(length)
		{ }
	};
	const char cigar_ops_as_chars[] = { 'M', 'I', 'D', 'N', 'S', 'H', 'P', '=', 'X', 'B' };

	class BamAlignment {

		bam1_t _bam;

		template <typename Destination>
		struct _TagGetterBase
		{
			_TagGetterBase(const BamAlignment& parent, Destination& dest) : _dest(dest), _parent(parent) {}
			Destination& _dest;
			const BamAlignment& _parent;
		};

		template <typename Left, typename Right>
		struct _TagGetter : _TagGetterBase<Right>
		{
			operator bool() { return false; }

			_TagGetter(const BamAlignment& parent, Right& right) : _TagGetterBase<Right>(parent, right) {}

			template <class MakeValue>
			bool operator()(const std::string tag, MakeValue make_value)
			{
				return false;
			}
		};

		template <typename Left>
		struct _TagGetter<Left, Left> : _TagGetterBase<Left>
		{
			operator bool() { return true; }

			_TagGetter(const BamAlignment& parent, Left& right) : _TagGetterBase<Left>(parent, right){};

			template <class MakeValue>
			bool operator ()(const std::string& tag, MakeValue make_value)
			{
				const uint8_t* data = bam_aux_get(this->_parent.HtsObj(), tag.c_str());
				if(nullptr == data) return false;
				this->_dest = make_value(data);
				return true;
			}
		};

	public:

		const bam1_t* HtsObj() const
		{
			return &_bam;
		}

		bam1_t* HtsObj2()
		{
			return &_bam;
		}

		std::string Name;
		std::string Filename;
		std::vector<CigarOp> CigarData;

		void InitCigarData()
		{
			CigarData.clear();

			uint32_t *cigar = bam_get_cigar(&_bam);
			uint32_t num_cigar_elements = _bam.core.n_cigar;

			for ( uint32_t i = 0; i < num_cigar_elements; ++i )
			{
				char type = cigar_ops_as_chars[static_cast<int>(bam_cigar_op(cigar[i]))];
				uint32_t len = bam_cigar_oplen(cigar[i]);
				CigarData.push_back(CigarOp(type, len));
			}
		}

		/* TODO: fix all this dummy strings What is TagData? Not from file? */
		std::string AlignedBases, Qualities, ErrorString, TagData;
		uint32_t BlockLength;

		std::string QueryBases;

		void InitAdditionalData()
		{
			QueryBases = "";
			static const char* base2char = "=ACMGRSVTWYHKDBN";
			const uint8_t* seq = bam_get_seq(&_bam);

			for(unsigned i = 0; i < QuerySequenceLength; i ++)
			{
				char cur_base = base2char[bam_seqi(seq, i)];
				QueryBases.push_back(cur_base);
			}

			Qualities = "";

			const uint8_t* qual = bam_get_qual(&_bam);

			if(_bam.core.l_qseq == 0 || qual[0] == 0xffu)
				Qualities.resize(QuerySequenceLength, -1);
			else for(unsigned i = 0; i < QuerySequenceLength; i ++)
				Qualities.push_back((char)(33 + qual[i]));
		}

#include <BamAlignment.mapping.hpp>

		struct _SupportData {
			_QueryNameLength_t& QueryNameLength;
			_QuerySequenceLength_t& QuerySequenceLength;
			_NumCigarOperations_t& NumCigarOperations;
			uint32_t& BlockLength;
			struct {
				const char* begin;
				size_t      size;
				const char* c_str() const { return begin; }
				size_t      length() const { return size; }
				void clear() { begin = NULL; size = 0; }
			} AllCharData;
			bool HasCoreOnly;  /* TODO(haohou): populate the string data */
			/* TODO(haohou): Tag2Cigar?  Real Cigar ? */
			_SupportData(BamAlignment& parent):
				QueryNameLength(parent.QueryNameLength),
				QuerySequenceLength(parent.QuerySequenceLength),
				NumCigarOperations(parent.NumCigarOperations),
				BlockLength(parent.BlockLength),
				HasCoreOnly(false)
			{
			}
		} SupportData;

		~BamAlignment()
		{
			free(_bam.data);
		}

		BamAlignment() : BlockLength(0), SupportData(*this)
		{
			memset(&_bam, 0, sizeof(_bam));
		}

		BamAlignment(const std::string& filename, const bam1_t* bam, uint32_t size = 0) :
			Name(bam_get_qname(bam)),
			Filename(filename),
			BlockLength(size),
			SupportData(*this)
		{
			bam_copy1(&_bam, bam);
			InitCigarData();
			InitAdditionalData();
		}

		BamAlignment(const BamAlignment& ba) :
			Filename(ba.Filename),
			SupportData(*this)
		{
			bam_copy1(&_bam, ba.HtsObj());
			CigarData = ba.CigarData;
			QueryBases = ba.QueryBases;
			Qualities = ba.Qualities;
			SupportData.AllCharData = ba.SupportData.AllCharData;
		}

		const BamAlignment& operator = (const BamAlignment& ba)
		{
			Name = ba.Name;
			Filename = ba.Filename;
			bam_copy1(&_bam, ba.HtsObj());
			BlockLength = ba.BlockLength;
			CigarData = ba.CigarData;
			QueryBases = ba.QueryBases;
			Qualities = ba.Qualities;
			SupportData.AllCharData = ba.SupportData.AllCharData;
			return *this;
		}

		void operator ()(const std::string filename, const bam1_t* bam, uint32_t size = 0, bool copy = true)
		{
			Filename = filename;
			Name = std::string(bam_get_qname(bam));
			BlockLength = size;
			if(copy)
				bam_copy1(&_bam, bam);
			else
			{
				free(_bam.data);
				_bam = *bam;
			}

			SupportData.AllCharData.begin = (const char*)_bam.data;
			SupportData.AllCharData.size = _bam.l_data;

			InitCigarData();
		}

		inline bool GetAlignmentFlag(uint32_t mask) const
		{
			return _bam.core.flag & mask;
		}

		inline void SetAlignmentFlag(uint32_t mask, bool val)
		{
			if(val && !(_bam.core.flag & mask))
				_bam.core.flag |= mask;
			else if(val && (_bam.core.flag & mask))
				_bam.core.flag &= ~mask;
		}

#define FLAG_ACCESSOR(name, mask) \
		inline bool Is##name() const { return GetAlignmentFlag(mask); }; \
		inline void SetIs##name(bool val) { SetAlignmentFlag(mask, val); };

		inline bool IsMapped() const
		{
			return !(_bam.core.flag & BAM_FUNMAP);
		}

		bool IsMateMapped() const
		{
			return !(_bam.core.flag & BAM_FMUNMAP);
		}

		FLAG_ACCESSOR(FirstMate, BAM_FREAD1);
		FLAG_ACCESSOR(SecondMate, BAM_FREAD2);
		FLAG_ACCESSOR(ReverseStrand, BAM_FREVERSE);
		FLAG_ACCESSOR(MateReverseStrand, BAM_FMREVERSE);
		FLAG_ACCESSOR(ProperPair, BAM_FPROPER_PAIR);
		FLAG_ACCESSOR(Paired, BAM_FPAIRED);
		FLAG_ACCESSOR(Duplicate, BAM_FDUP);
		FLAG_ACCESSOR(FailedQC, BAM_FQCFAIL);

		int GetEndPosition(bool usePadded = false, bool closedInterval = false) const
		{
			if(usePadded || closedInterval)
			{
				fprintf(stderr, "FIXME: we current do not support the usePadded and closedInterval param");
			}

			return bam_endpos(&_bam);
		}

		template <typename T>
		bool GetTag(const std::string& tag, T& destination) const
		{

			_TagGetter<std::string, T> string_getter(*this, destination);
			if(string_getter)
				return string_getter(tag, _mkstr);
			return false;
		}

		bool HasTag(const std::string& tag) const
		{
			const uint8_t *aux_ptr = bam_aux_get(&_bam, tag.c_str());
			if ( aux_ptr == nullptr )
				return false;
			return true;
		}

		template <typename T>
		bool AddTag(const std::string& tag, const std::string& type, T data)
		{
			_TagGetter<std::string, T> string_getter(*this, data);
			if(string_getter && "Z" == type)
			{
				std::string* str = static_cast<std::string*>(&data);
				bam_aux_append(&_bam, tag.c_str(), 'Z', str->size() + 1, (uint8_t*)str->c_str());
				return true;
			}
			return false;
		}

	};
}
#endif
<|endoftext|>


<commit_before>//-------------------------------------------------------------------------------------------------------
// Copyright (C) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE.txt file in the project root for full license information.
//-------------------------------------------------------------------------------------------------------
#include "RuntimeLibraryPch.h"

#ifdef ENABLE_WABT
#include "../WasmReader/WasmReaderPch.h"

#include "ast-lexer.h"
#include "common.h"
#include "ast.h"
#include "ast-parser.h"
#include "binary-writer.h"
#include "binary-writer-spec.h"
#include "resolve-names.h"
#include "validator.h"
#include "Codex/Utf8Helper.h"
using namespace wabt;

ArenaAllocator* tempArenaPtr;
struct utf8Allocator
{
    static byte* allocate(size_t size)
    {
        return AnewArray(tempArenaPtr, byte, size);
    }
};

struct MemoryWriterContext
{
    MemoryWriter* writer;
    ArenaAllocator* alloc;
};

void ensure_output_buffer_capacity(OutputBuffer* buf, size_t ensure_capacity, MemoryWriterContext* context)
{
    if (ensure_capacity > buf->capacity)
    {
        Assert(buf->capacity != 0);
        size_t newCapacity = buf->capacity * 2;
        while (newCapacity < ensure_capacity)
            newCapacity *= 2;
        char* new_data = AnewArrayZ(context->alloc, char, newCapacity);
        js_memcpy_s(new_data, newCapacity, buf->start, buf->capacity);
        buf->start = new_data;
        buf->capacity = newCapacity;
    }
}

wabt::Result write_data_to_output_buffer(size_t offset,
                                          const void* data,
                                          size_t size,
                                          void* user_data)
{
    MemoryWriterContext* context = static_cast<MemoryWriterContext*>(user_data);
    MemoryWriter* writer = context->writer;
    size_t end = offset + size;
    ensure_output_buffer_capacity(&writer->buf, end, context);
    memcpy(writer->buf.start + offset, data, size);
    if (end > writer->buf.size)
        writer->buf.size = end;
    return Result::Ok;
}

wabt::Result move_data_in_output_buffer(size_t dst_offset,
                                         size_t src_offset,
                                         size_t size,
                                         void* user_data)
{
    MemoryWriterContext* context = static_cast<MemoryWriterContext*>(user_data);
    MemoryWriter* writer = context->writer;
    size_t src_end = src_offset + size;
    size_t dst_end = dst_offset + size;
    size_t end = src_end > dst_end ? src_end : dst_end;
    ensure_output_buffer_capacity(&writer->buf, end, context);
    void* dst = reinterpret_cast<void*>(
        reinterpret_cast<size_t>(writer->buf.start) + dst_offset);
    void* src = reinterpret_cast<void*>(
        reinterpret_cast<size_t>(writer->buf.start) + src_offset);
    memmove(dst, src, size);
    if (end > writer->buf.size)
        writer->buf.size = end;
    return Result::Ok;
}

Js::Var Js::WabtInterface::EntryConvertWast2Wasm(RecyclableObject* function, CallInfo callInfo, ...)
{
    Js::ScriptContext* scriptContext = function->GetScriptContext();
    Var returnValue = scriptContext->GetLibrary()->GetUndefined();
    PROBE_STACK(function->GetScriptContext(), Js::Constants::MinStackDefault);

    ARGUMENTS(args, callInfo);
    AssertMsg(args.Info.Count > 0, "Should always have implicit 'this'");

    Assert(!(callInfo.Flags & CallFlags_New));

    if (args.Info.Count < 2 || !Js::JavascriptString::Is(args[1]))
    {
        JavascriptError::ThrowTypeError(scriptContext, WASMERR_NeedBufferSource);
    }
    Js::JavascriptString* string = (Js::JavascriptString*)args[1];
    const char16* str = string->GetString();
    ArenaAllocator arena(_u("Wast2Wasm"), scriptContext->GetThreadContext()->GetPageAllocator(), Js::Throw::OutOfMemory);
    size_t origSize = string->GetLength();
    size_t wastSize;
    char* wastBuffer = nullptr;
    tempArenaPtr = &arena;
    utf8::WideStringToNarrow<utf8Allocator>(str, origSize, &wastBuffer, &wastSize);

    AstLexer* lexer = new_ast_buffer_lexer("", wastBuffer, wastSize);
    struct AutoCleanLexer
    {
        AstLexer* lexer;
        ~AutoCleanLexer()
        {
            wabt::destroy_ast_lexer(lexer);
        }
    };
    AutoCleanLexer autoCleanLexer = { lexer };

    auto errorCallback = [](const wabt::Location*,
                            const char* error,
                            const char* source_line,
                            size_t source_line_length,
                            size_t source_line_column_offset,
                            void* user_data)
    {
        Js::JavascriptError::ThrowError((ScriptContext*)user_data, WASMERR_WasmCompileError);
    };
    wabt::SourceErrorHandler s_error_handler = {
        errorCallback,
        120,
        scriptContext
    };
    bool s_validate = true;

    wabt::Script script;
    wabt::Result result = wabt::parse_ast(lexer, &script, &s_error_handler);
    struct AutoCleanScript
    {
        wabt::Script* script;
        ~AutoCleanScript()
        {
            wabt::destroy_script(script);
        }
    };
    AutoCleanScript autoCleanScript = { &script };

    //wabt::WriteBinarySpecOptions s_write_binary_spec_options;

    if (WABT_SUCCEEDED(result))
    {
        result = wabt::resolve_names_script(lexer, &script, &s_error_handler);

        if (WABT_SUCCEEDED(result) && s_validate)
            result = wabt::validate_script(lexer, &script, &s_error_handler);

        if (WABT_SUCCEEDED(result))
        {
            /*
            if (s_spec)
            {
                s_write_binary_spec_options.json_filename = s_outfile;
                s_write_binary_spec_options.write_binary_options =
                    s_write_binary_options;
                result = write_binary_spec_script(&script, s_infile,
                                                  &s_write_binary_spec_options);
            }
            else
            */
            {
                MemoryWriter writer;
                MemoryWriterContext context{ &writer, &arena };
                writer.base.move_data = move_data_in_output_buffer;
                writer.base.write_data = write_data_to_output_buffer;
                writer.base.user_data = &context;
                writer.buf.size = 0;
                writer.buf.capacity = 256;
                writer.buf.start = AnewArrayZ(&arena, char, writer.buf.capacity);
                Module* module = get_first_module(&script);
                if (module)
                {
                    wabt::WriteBinaryOptions s_write_binary_options = { nullptr, true, false, false };
                    result = write_binary_module(&writer.base, module, &s_write_binary_options);
                }
                else
                {
                    WABT_FATAL("no module found\n");
                }

                if (WABT_SUCCEEDED(result))
                {
                    uint32 size = (uint32)writer.buf.size;
                    Js::ArrayBuffer* arrayBuffer = scriptContext->GetLibrary()->CreateArrayBuffer(size);
                    js_memcpy_s(arrayBuffer->GetBuffer(), arrayBuffer->GetByteLength(), writer.buf.start, size);
                    returnValue = arrayBuffer;
                }
            }
        }
    }
    return returnValue;
}
#endif // ENABLE_WABT
<commit_msg>Fix legacy build<commit_after>//-------------------------------------------------------------------------------------------------------
// Copyright (C) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE.txt file in the project root for full license information.
//-------------------------------------------------------------------------------------------------------
#include "RuntimeLibraryPch.h"

#ifdef ENABLE_WABT
#include "../WasmReader/WasmReaderPch.h"

#include "ast-lexer.h"
#include "common.h"
#include "ast.h"
#include "ast-parser.h"
#include "binary-writer.h"
#include "binary-writer-spec.h"
#include "resolve-names.h"
#include "validator.h"
#include "Codex/Utf8Helper.h"
using namespace wabt;

ArenaAllocator* tempArenaPtr;
struct utf8Allocator
{
    static byte* allocate(size_t size)
    {
        return AnewArray(tempArenaPtr, byte, size);
    }
};

struct MemoryWriterContext
{
    MemoryWriter* writer;
    ArenaAllocator* alloc;
};

void ensure_output_buffer_capacity(OutputBuffer* buf, size_t ensure_capacity, MemoryWriterContext* context)
{
    if (ensure_capacity > buf->capacity)
    {
        Assert(buf->capacity != 0);
        size_t newCapacity = buf->capacity * 2;
        while (newCapacity < ensure_capacity)
            newCapacity *= 2;
        char* new_data = AnewArrayZ(context->alloc, char, newCapacity);
        js_memcpy_s(new_data, newCapacity, buf->start, buf->capacity);
        buf->start = new_data;
        buf->capacity = newCapacity;
    }
}

wabt::Result write_data_to_output_buffer(size_t offset,
                                          const void* data,
                                          size_t size,
                                          void* user_data)
{
    MemoryWriterContext* context = static_cast<MemoryWriterContext*>(user_data);
    MemoryWriter* writer = context->writer;
    size_t end = offset + size;
    ensure_output_buffer_capacity(&writer->buf, end, context);
    memcpy(writer->buf.start + offset, data, size);
    if (end > writer->buf.size)
        writer->buf.size = end;
    return Result::Ok;
}

wabt::Result move_data_in_output_buffer(size_t dst_offset,
                                         size_t src_offset,
                                         size_t size,
                                         void* user_data)
{
    MemoryWriterContext* context = static_cast<MemoryWriterContext*>(user_data);
    MemoryWriter* writer = context->writer;
    size_t src_end = src_offset + size;
    size_t dst_end = dst_offset + size;
    size_t end = src_end > dst_end ? src_end : dst_end;
    ensure_output_buffer_capacity(&writer->buf, end, context);
    void* dst = reinterpret_cast<void*>(
        reinterpret_cast<size_t>(writer->buf.start) + dst_offset);
    void* src = reinterpret_cast<void*>(
        reinterpret_cast<size_t>(writer->buf.start) + src_offset);
    memmove(dst, src, size);
    if (end > writer->buf.size)
        writer->buf.size = end;
    return Result::Ok;
}

Js::Var Js::WabtInterface::EntryConvertWast2Wasm(RecyclableObject* function, CallInfo callInfo, ...)
{
    Js::ScriptContext* scriptContext = function->GetScriptContext();
    Var returnValue = scriptContext->GetLibrary()->GetUndefined();
    PROBE_STACK(function->GetScriptContext(), Js::Constants::MinStackDefault);

    ARGUMENTS(args, callInfo);
    AssertMsg(args.Info.Count > 0, "Should always have implicit 'this'");

    Assert(!(callInfo.Flags & CallFlags_New));

    if (args.Info.Count < 2 || !Js::JavascriptString::Is(args[1]))
    {
        JavascriptError::ThrowTypeError(scriptContext, WASMERR_NeedBufferSource);
    }
    Js::JavascriptString* string = (Js::JavascriptString*)args[1];
    const char16* str = string->GetString();
    ArenaAllocator arena(_u("Wast2Wasm"), scriptContext->GetThreadContext()->GetPageAllocator(), Js::Throw::OutOfMemory);
    size_t origSize = string->GetLength();
    size_t wastSize;
    char* wastBuffer = nullptr;
    tempArenaPtr = &arena;
    utf8::WideStringToNarrow<utf8Allocator>(str, origSize, &wastBuffer, &wastSize);

    AstLexer* lexer = new_ast_buffer_lexer("", wastBuffer, wastSize);
    struct AutoCleanLexer
    {
        AstLexer* lexer;
        ~AutoCleanLexer()
        {
            wabt::destroy_ast_lexer(lexer);
        }
    };
    AutoCleanLexer autoCleanLexer = { lexer };
    Unused(autoCleanLexer);

    auto errorCallback = [](const wabt::Location*,
                            const char* error,
                            const char* source_line,
                            size_t source_line_length,
                            size_t source_line_column_offset,
                            void* user_data)
    {
        Js::JavascriptError::ThrowError((ScriptContext*)user_data, WASMERR_WasmCompileError);
    };
    wabt::SourceErrorHandler s_error_handler = {
        errorCallback,
        120,
        scriptContext
    };
    bool s_validate = true;

    wabt::Script script;
    wabt::Result result = wabt::parse_ast(lexer, &script, &s_error_handler);
    struct AutoCleanScript
    {
        wabt::Script* script;
        ~AutoCleanScript()
        {
            wabt::destroy_script(script);
        }
    };
    AutoCleanScript autoCleanScript = { &script };
    Unused(autoCleanScript);

    //wabt::WriteBinarySpecOptions s_write_binary_spec_options;

    if (WABT_SUCCEEDED(result))
    {
        result = wabt::resolve_names_script(lexer, &script, &s_error_handler);

        if (WABT_SUCCEEDED(result) && s_validate)
            result = wabt::validate_script(lexer, &script, &s_error_handler);

        if (WABT_SUCCEEDED(result))
        {
            /*
            if (s_spec)
            {
                s_write_binary_spec_options.json_filename = s_outfile;
                s_write_binary_spec_options.write_binary_options =
                    s_write_binary_options;
                result = write_binary_spec_script(&script, s_infile,
                                                  &s_write_binary_spec_options);
            }
            else
            */
            {
                MemoryWriter writer;
                MemoryWriterContext context{ &writer, &arena };
                writer.base.move_data = move_data_in_output_buffer;
                writer.base.write_data = write_data_to_output_buffer;
                writer.base.user_data = &context;
                writer.buf.size = 0;
                writer.buf.capacity = 256;
                writer.buf.start = AnewArrayZ(&arena, char, writer.buf.capacity);
                Module* module = get_first_module(&script);
                if (module)
                {
                    wabt::WriteBinaryOptions s_write_binary_options = { nullptr, true, false, false };
                    result = write_binary_module(&writer.base, module, &s_write_binary_options);
                }
                else
                {
                    WABT_FATAL("no module found\n");
                }

                if (WABT_SUCCEEDED(result))
                {
                    uint32 size = (uint32)writer.buf.size;
                    Js::ArrayBuffer* arrayBuffer = scriptContext->GetLibrary()->CreateArrayBuffer(size);
                    js_memcpy_s(arrayBuffer->GetBuffer(), arrayBuffer->GetByteLength(), writer.buf.start, size);
                    returnValue = arrayBuffer;
                }
            }
        }
    }
    return returnValue;
}
#endif // ENABLE_WABT
<|endoftext|>


<commit_before>#include "IECore/PointBoundsOp.h"
#include "IECore/VectorTypedData.h"
#include "IECore/ObjectParameter.h"
#include "IECore/CompoundParameter.h"
#include "IECore/TypedParameter.h"
#include "IECore/VectorTypedData.h"
#include "IECore/CompoundObject.h"
#include "IECore/Object.h"

using namespace IECore;
using namespace Imath;
using namespace std;
using namespace boost;

static TypeId pointAndVelocityTypes[] = { V3fVectorDataTypeId, V3dVectorDataTypeId, InvalidTypeId };
static TypeId radiusTypes[] = { FloatVectorDataTypeId, DoubleVectorDataTypeId, InvalidTypeId };

PointBoundsOp::PointBoundsOp()
	:	Op(
		staticTypeName(),
		"Calculates the bounding box for a volume of points.",
		new Box3fParameter(
			"result",
			"The bounding box for the points.",
			Box3f()
		)
	)
{
	m_pointParameter = new ObjectParameter(
		"points",
		"The points to calculate normals for.",
		new V3fVectorData(),
		pointAndVelocityTypes
	);
	m_velocityParameter = new ObjectParameter(
		"velocities",
		"The velocities for the points.",
		new V3fVectorData,
		pointAndVelocityTypes
	);
	m_velocityMultiplierParameter = new FloatParameter(
		"velocityMultiplier",
		"A multiplier for the velocity values.",
		1.0f
	);
	m_radiusParameter = new ObjectParameter(
		"radii",
		"The radii for the points.",
		new FloatVectorData,
		radiusTypes
	);
	m_radiusMultiplierParameter = new FloatParameter(
		"radiusMultiplier",
		"A multiplier for the radius values.",
		1.0f
	);
	parameters()->addParameter( m_pointParameter );
	parameters()->addParameter( m_velocityParameter );
	parameters()->addParameter( m_velocityMultiplierParameter );
	parameters()->addParameter( m_radiusParameter );
	parameters()->addParameter( m_radiusMultiplierParameter );
}

PointBoundsOp::~PointBoundsOp()
{
}

ObjectParameterPtr PointBoundsOp::pointParameter()
{
	return m_pointParameter;
}

ConstObjectParameterPtr PointBoundsOp::pointParameter() const
{
	return m_pointParameter;
}

ObjectParameterPtr PointBoundsOp::radiusParameter()
{
	return m_radiusParameter;
}

ConstObjectParameterPtr PointBoundsOp::radiusParameter() const
{
	return m_radiusParameter;
}

ObjectParameterPtr PointBoundsOp::velocityParameter()
{
	return m_velocityParameter;
}

ConstObjectParameterPtr PointBoundsOp::velocityParameter() const
{
	return m_velocityParameter;
}

template<typename P, typename R, typename V>
static Box3fDataPtr bound3( typename P::ConstPtr pData, typename R::ConstPtr rData, float rMult, typename V::ConstPtr vData, float vMult )
{
	typedef typename P::ValueType::value_type Point;
	typedef typename V::ValueType::value_type Vector;
	typedef typename R::ValueType::value_type Radius;

	Box3f result;
	const typename P::ValueType &pVector = pData->readable();

	size_t vLength = 0;
	const Vector *v = 0;
	if( vData && vData->readable().size() )
	{
		vLength = vData->readable().size();
		v = &(vData->readable()[0]);
	}

	size_t rLength = 0;
	const Radius *r = 0;
	if( rData && rData->readable().size() )
	{
		rLength = rData->readable().size();
		r = &(rData->readable()[0]);
	}

	size_t i = 0;
	for( typename P::ValueType::const_iterator pIt = pVector.begin(); pIt!=pVector.end(); pIt++ )
	{
		Box3f b;
		b.extendBy( *pIt );
		if( v && i<vLength )
		{
			b.extendBy( *pIt + v[i] * vMult );
		}
		if( r && i<rLength )
		{
			Point rr( r[i] * rMult );
			b.min -= rr;
			b.max += rr;

		}
		result.extendBy( b );
		i++;
	}
	return new Box3fData( result );
}

template<typename P, typename R>
static Box3fDataPtr bound2( typename P::ConstPtr pData, typename R::ConstPtr rData, float rMult, ConstObjectPtr vData, float vMult )
{
	switch( vData->typeId() )
	{
		case V3fVectorDataTypeId :
			return bound3<P, R, V3fVectorData>( pData, rData, rMult, static_pointer_cast<const V3fVectorData>( vData ), vMult );
		case V3dVectorDataTypeId :
			return bound3<P, R, V3dVectorData>( pData, rData, rMult, static_pointer_cast<const V3dVectorData>( vData ), vMult );
		default :
			assert( 0 ); // parameter validation should prevent us getting here
	}
	return 0;
}

template<typename P>
static Box3fDataPtr bound1( typename P::ConstPtr pData, ConstObjectPtr rData, float rMult, ConstObjectPtr vData, float vMult )
{
	switch( rData->typeId() )
	{
		case FloatVectorDataTypeId :
			return bound2<P, FloatVectorData>( pData, static_pointer_cast<const FloatVectorData>( rData ), rMult, vData, vMult );
		case DoubleVectorDataTypeId :
			return bound2<P, DoubleVectorData>( pData, static_pointer_cast<const DoubleVectorData>( rData ), rMult, vData, vMult );
		default :
			assert( 0 ); // parameter validation should prevent us getting here
	}
	return 0;
}

ObjectPtr PointBoundsOp::doOperation( ConstCompoundObjectPtr operands )
{
	ConstObjectPtr p = m_pointParameter->getValue();
	ConstObjectPtr v = m_velocityParameter->getValue();
	ConstObjectPtr r = m_radiusParameter->getValue();
	float vm = m_velocityMultiplierParameter->getNumericValue();
	float rm = m_radiusMultiplierParameter->getNumericValue();
	switch( p->typeId() )
	{
		case V3fVectorDataTypeId :
			return bound1<V3fVectorData>( static_pointer_cast<const V3fVectorData>( p ), r, rm, v, vm );
		case V3dVectorDataTypeId :
			return bound1<V3dVectorData>( static_pointer_cast<const V3dVectorData>( p ), r, rm, v, vm );
		default :
			assert( 0 ); // parameter validation should prevent us getting here
	}
	return 0;
}
<commit_msg>Added the license text.<commit_after>//////////////////////////////////////////////////////////////////////////
//
//  Copyright (c) 2007, Image Engine Design Inc. All rights reserved.
//
//  Redistribution and use in source and binary forms, with or without
//  modification, are permitted provided that the following conditions are
//  met:
//
//     * Redistributions of source code must retain the above copyright
//       notice, this list of conditions and the following disclaimer.
//
//     * Redistributions in binary form must reproduce the above copyright
//       notice, this list of conditions and the following disclaimer in the
//       documentation and/or other materials provided with the distribution.
//
//     * Neither the name of Image Engine Design nor the names of any
//       other contributors to this software may be used to endorse or
//       promote products derived from this software without specific prior
//       written permission.
//
//  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
//  IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
//  THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
//  PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
//  CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
//  EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
//  PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
//  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
//  LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
//  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
//  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
//////////////////////////////////////////////////////////////////////////

#include "IECore/PointBoundsOp.h"
#include "IECore/VectorTypedData.h"
#include "IECore/ObjectParameter.h"
#include "IECore/CompoundParameter.h"
#include "IECore/TypedParameter.h"
#include "IECore/VectorTypedData.h"
#include "IECore/CompoundObject.h"
#include "IECore/Object.h"

using namespace IECore;
using namespace Imath;
using namespace std;
using namespace boost;

static TypeId pointAndVelocityTypes[] = { V3fVectorDataTypeId, V3dVectorDataTypeId, InvalidTypeId };
static TypeId radiusTypes[] = { FloatVectorDataTypeId, DoubleVectorDataTypeId, InvalidTypeId };

PointBoundsOp::PointBoundsOp()
	:	Op(
		staticTypeName(),
		"Calculates the bounding box for a volume of points.",
		new Box3fParameter(
			"result",
			"The bounding box for the points.",
			Box3f()
		)
	)
{
	m_pointParameter = new ObjectParameter(
		"points",
		"The points to calculate normals for.",
		new V3fVectorData(),
		pointAndVelocityTypes
	);
	m_velocityParameter = new ObjectParameter(
		"velocities",
		"The velocities for the points.",
		new V3fVectorData,
		pointAndVelocityTypes
	);
	m_velocityMultiplierParameter = new FloatParameter(
		"velocityMultiplier",
		"A multiplier for the velocity values.",
		1.0f
	);
	m_radiusParameter = new ObjectParameter(
		"radii",
		"The radii for the points.",
		new FloatVectorData,
		radiusTypes
	);
	m_radiusMultiplierParameter = new FloatParameter(
		"radiusMultiplier",
		"A multiplier for the radius values.",
		1.0f
	);
	parameters()->addParameter( m_pointParameter );
	parameters()->addParameter( m_velocityParameter );
	parameters()->addParameter( m_velocityMultiplierParameter );
	parameters()->addParameter( m_radiusParameter );
	parameters()->addParameter( m_radiusMultiplierParameter );
}

PointBoundsOp::~PointBoundsOp()
{
}

ObjectParameterPtr PointBoundsOp::pointParameter()
{
	return m_pointParameter;
}

ConstObjectParameterPtr PointBoundsOp::pointParameter() const
{
	return m_pointParameter;
}

ObjectParameterPtr PointBoundsOp::radiusParameter()
{
	return m_radiusParameter;
}

ConstObjectParameterPtr PointBoundsOp::radiusParameter() const
{
	return m_radiusParameter;
}

ObjectParameterPtr PointBoundsOp::velocityParameter()
{
	return m_velocityParameter;
}

ConstObjectParameterPtr PointBoundsOp::velocityParameter() const
{
	return m_velocityParameter;
}

template<typename P, typename R, typename V>
static Box3fDataPtr bound3( typename P::ConstPtr pData, typename R::ConstPtr rData, float rMult, typename V::ConstPtr vData, float vMult )
{
	typedef typename P::ValueType::value_type Point;
	typedef typename V::ValueType::value_type Vector;
	typedef typename R::ValueType::value_type Radius;

	Box3f result;
	const typename P::ValueType &pVector = pData->readable();

	size_t vLength = 0;
	const Vector *v = 0;
	if( vData && vData->readable().size() )
	{
		vLength = vData->readable().size();
		v = &(vData->readable()[0]);
	}

	size_t rLength = 0;
	const Radius *r = 0;
	if( rData && rData->readable().size() )
	{
		rLength = rData->readable().size();
		r = &(rData->readable()[0]);
	}

	size_t i = 0;
	for( typename P::ValueType::const_iterator pIt = pVector.begin(); pIt!=pVector.end(); pIt++ )
	{
		Box3f b;
		b.extendBy( *pIt );
		if( v && i<vLength )
		{
			b.extendBy( *pIt + v[i] * vMult );
		}
		if( r && i<rLength )
		{
			Point rr( r[i] * rMult );
			b.min -= rr;
			b.max += rr;

		}
		result.extendBy( b );
		i++;
	}
	return new Box3fData( result );
}

template<typename P, typename R>
static Box3fDataPtr bound2( typename P::ConstPtr pData, typename R::ConstPtr rData, float rMult, ConstObjectPtr vData, float vMult )
{
	switch( vData->typeId() )
	{
		case V3fVectorDataTypeId :
			return bound3<P, R, V3fVectorData>( pData, rData, rMult, static_pointer_cast<const V3fVectorData>( vData ), vMult );
		case V3dVectorDataTypeId :
			return bound3<P, R, V3dVectorData>( pData, rData, rMult, static_pointer_cast<const V3dVectorData>( vData ), vMult );
		default :
			assert( 0 ); // parameter validation should prevent us getting here
	}
	return 0;
}

template<typename P>
static Box3fDataPtr bound1( typename P::ConstPtr pData, ConstObjectPtr rData, float rMult, ConstObjectPtr vData, float vMult )
{
	switch( rData->typeId() )
	{
		case FloatVectorDataTypeId :
			return bound2<P, FloatVectorData>( pData, static_pointer_cast<const FloatVectorData>( rData ), rMult, vData, vMult );
		case DoubleVectorDataTypeId :
			return bound2<P, DoubleVectorData>( pData, static_pointer_cast<const DoubleVectorData>( rData ), rMult, vData, vMult );
		default :
			assert( 0 ); // parameter validation should prevent us getting here
	}
	return 0;
}

ObjectPtr PointBoundsOp::doOperation( ConstCompoundObjectPtr operands )
{
	ConstObjectPtr p = m_pointParameter->getValue();
	ConstObjectPtr v = m_velocityParameter->getValue();
	ConstObjectPtr r = m_radiusParameter->getValue();
	float vm = m_velocityMultiplierParameter->getNumericValue();
	float rm = m_radiusMultiplierParameter->getNumericValue();
	switch( p->typeId() )
	{
		case V3fVectorDataTypeId :
			return bound1<V3fVectorData>( static_pointer_cast<const V3fVectorData>( p ), r, rm, v, vm );
		case V3dVectorDataTypeId :
			return bound1<V3dVectorData>( static_pointer_cast<const V3dVectorData>( p ), r, rm, v, vm );
		default :
			assert( 0 ); // parameter validation should prevent us getting here
	}
	return 0;
}
<|endoftext|>