<commit_before>/*
 * ---------------------------------------------------------------------
 * Numenta Platform for Intelligent Computing (NuPIC)
 * Copyright (C) 2013, Numenta, Inc.  Unless you have purchased from
 * Numenta, Inc. a separate commercial license for this software code, the
 * following terms and conditions apply:
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 3 as
 * published by the Free Software Foundation.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 * See the GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see http://www.gnu.org/licenses.
 *
 * http://numenta.org/licenses/
 * ---------------------------------------------------------------------
 */

#include <iostream>

#include <nta/engine/RegionImpl.hpp>
#include <nta/ntypes/Buffer.hpp>
#include <nta/ntypes/Array.hpp>
#include <nta/types/BasicType.hpp>
#include <nta/engine/Region.hpp>
#include <nta/engine/Spec.hpp>
#include <nta/ntypes/Dimensions.hpp>
#include <nta/ntypes/BundleIO.hpp>
#include <nta/os/FStream.hpp>

namespace nta
{

RegionImpl::RegionImpl(Region *region) :
  region_(region)
{
}

RegionImpl::~RegionImpl()
{
}

// convenience method
const std::string& RegionImpl::getType() const
{
  return region_->getType();
}

const std::string& RegionImpl::getName() const
{
  return region_->getName();
}

const NodeSet& RegionImpl::getEnabledNodes() const
{
  return region_->getEnabledNodes();
}

/* ------------- Parameter support --------------- */
// By default, all typed getParameter calls forward to the
// untyped getParameter that serializes to a buffer

// Use macros to implement these methods.
// This is similar to a template + explicit instantiation, but
// templated methods can't be virtual and thus can't be
// overridden by subclasses.

#define getParameterT(Type) \
Type RegionImpl::getParameter##Type(const std::string& name, Int64 index) \
{\
  if (! region_->getSpec()->parameters.contains(name))     \
    NTA_THROW << "getParameter" #Type ": parameter " << name << " does not exist in nodespec"; \
  ParameterSpec p = region_->getSpec()->parameters.getByName(name); \
  if (p.dataType != NTA_BasicType_ ## Type) \
    NTA_THROW << "getParameter" #Type ": parameter " << name << " is of type " \
              << BasicType::getName(p.dataType) << " not " #Type; \
  WriteBuffer wb; \
  getParameterFromBuffer(name, index, wb); \
  ReadBuffer rb(wb.getData(), wb.getSize(), false /* copy */); \
  Type val; \
  int rc = rb.read(val); \
  if (rc != 0)  \
  { \
    NTA_THROW << "getParameter" #Type " -- failure to get parameter '"  \
              << name << "' on node of type " << getType(); \
  } \
  return val; \
}

getParameterT(Int32);
getParameterT(UInt32);
getParameterT(Int64);
getParameterT(UInt64)
getParameterT(Real32);
getParameterT(Real64);

#define setParameterT(Type) \
void RegionImpl::setParameter##Type(const std::string& name, Int64 index, Type value) \
{ \
  WriteBuffer wb; \
  wb.write((Type)value); \
  ReadBuffer rb(wb.getData(), wb.getSize(), false /* copy */); \
  setParameterFromBuffer(name, index, rb); \
}

setParameterT(Int32);
setParameterT(UInt32);
setParameterT(Int64);
setParameterT(UInt64)
setParameterT(Real32);
setParameterT(Real64);

// buffer mechanism can't handle Handles. RegionImpl must override these methods.
Handle RegionImpl::getParameterHandle(const std::string& name, Int64 index)
{
  NTA_THROW << "Unknown parameter '"  << name << "' of type Handle.";
}

void RegionImpl::setParameterHandle(const std::string& name, Int64 index, Handle h)
{
  NTA_THROW << "Unknown parameter '"  << name << "' of type Handle.";
}

void RegionImpl::getParameterArray(const std::string& name, Int64 index, Array & array)
{
  WriteBuffer wb;
  getParameterFromBuffer(name, index, wb);
  ReadBuffer rb(wb.getData(), wb.getSize(), false /* copy */);
  size_t count = array.getCount();
  void *buffer = array.getBuffer();

  for (size_t i = 0; i < count; i++)
  {
    int rc;
    switch (array.getType())
    {

    case NTA_BasicType_Byte:
      rc = rb.read(((Byte*)buffer)[i]);
      break;
    case NTA_BasicType_Int32:
      rc = rb.read(((Int32*)buffer)[i]);
      break;
    case NTA_BasicType_UInt32:
      rc = rb.read(((UInt32*)buffer)[i]);
      break;
    case NTA_BasicType_Int64:
      rc = rb.read(((Int64*)buffer)[i]);
      break;
    case NTA_BasicType_UInt64:
      rc = rb.read(((UInt64*)buffer)[i]);
      break;
    case NTA_BasicType_Real32:
      rc = rb.read(((Real32*)buffer)[i]);
      break;
    case NTA_BasicType_Real64:
      rc = rb.read(((Real64*)buffer)[i]);
      break;
    default:
      NTA_THROW << "Unsupported basic type " << BasicType::getName(array.getType())
                << " in getParameterArray for parameter " << name;
      break;
    }

    if (rc != 0)
    {
      NTA_THROW << "getParameterArray -- failure to get parameter '"
                << name << "' on node of type " << getType();
    }
  }
  return;
}

void RegionImpl::setParameterArray(const std::string& name, Int64 index,const Array & array)
{
  WriteBuffer wb;
  size_t count = array.getCount();
  void *buffer = array.getBuffer();
  for (size_t i = 0; i < count; i++)
  {
    int rc;
    switch (array.getType())
    {

    case NTA_BasicType_Byte:
      rc = wb.write(((Byte*)buffer)[i]);
      break;
    case NTA_BasicType_Int32:
      rc = wb.write(((Int32*)buffer)[i]);
      break;
    case NTA_BasicType_UInt32:
      rc = wb.write(((UInt32*)buffer)[i]);
      break;
    case NTA_BasicType_Int64:
      rc = wb.write(((Int64*)buffer)[i]);
      break;
    case NTA_BasicType_UInt64:
      rc = wb.write(((UInt64*)buffer)[i]);
      break;
    case NTA_BasicType_Real32:
      rc = wb.write(((Real32*)buffer)[i]);
      break;
    case NTA_BasicType_Real64:
      rc = wb.write(((Real64*)buffer)[i]);
      break;
    default:
      NTA_THROW << "Unsupported basic type " << BasicType::getName(array.getType())
                << " in setParameterArray for parameter " << name;
      break;
    }

    if (rc != 0)
    {
      NTA_THROW << "getParameterArray -- failure to get parameter '"
                << name << "' on node of type " << getType();
    }
  }

  ReadBuffer rb(wb.getData(), wb.getSize(), false);
  setParameterFromBuffer(name, index, rb);
}

void RegionImpl::setParameterString(const std::string& name, Int64 index, const std::string& s)
{
  ReadBuffer rb(s.c_str(), s.size(), false);
  setParameterFromBuffer(name, index, rb);
}

std::string RegionImpl::getParameterString(const std::string& name, Int64 index)
{
  WriteBuffer wb;
  getParameterFromBuffer(name, index, wb);
  return std::string(wb.getData(), wb.getSize());
}

// Must be overridden by subclasses
bool RegionImpl::isParameterShared(const std::string& name)
{
  NTA_THROW << "RegionImpl::isParameterShared was not overridden in node type " << getType();
}

void RegionImpl::getParameterFromBuffer(const std::string& name,
                             Int64 index,
                             IWriteBuffer& value)
{
  NTA_THROW << "RegionImpl::getParameterFromBuffer must be overridden by subclasses";
}

void RegionImpl::setParameterFromBuffer(const std::string& name,
                          Int64 index,
                          IReadBuffer& value)
{
  NTA_THROW << "RegionImpl::setParameterFromBuffer must be overridden by subclasses";
}

size_t RegionImpl::getParameterArrayCount(const std::string& name, Int64 index)
{
  // Default implementation for RegionImpls with no array parameters
  // that have a dynamic length.
  //std::map<std::string, ParameterSpec*>::iterator i = nodespec_->parameters.find(name);
  //if (i == nodespec_->parameters.end())

  if (!region_->getSpec()->parameters.contains(name))
  {
    NTA_THROW << "getParameterArrayCount -- no parameter named '"
              << name << "' in node of type " << getType();
  }
  UInt32 count = region_->getSpec()->parameters.getByName(name).count;
  if (count == 0)
  {
    NTA_THROW << "Internal Error -- unknown element count for "
              << "node type " << getType() << ". The RegionImpl "
              << "implementation should override this method.";
  }

  return count;
}

// Provide data access for subclasses

const Input* RegionImpl::getInput(const std::string& name)
{
  return region_->getInput(name);
}

const Output* RegionImpl::getOutput(const std::string& name)
{
  return region_->getOutput(name);
}

const Dimensions& RegionImpl::getDimensions()
{
  return region_->getDimensions();
}

}

<commit_msg>use NTA_ASSERT in check<commit_after>/*
 * ---------------------------------------------------------------------
 * Numenta Platform for Intelligent Computing (NuPIC)
 * Copyright (C) 2013, Numenta, Inc.  Unless you have purchased from
 * Numenta, Inc. a separate commercial license for this software code, the
 * following terms and conditions apply:
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 3 as
 * published by the Free Software Foundation.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 * See the GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see http://www.gnu.org/licenses.
 *
 * http://numenta.org/licenses/
 * ---------------------------------------------------------------------
 */

#include <iostream>

#include <nta/engine/RegionImpl.hpp>
#include <nta/ntypes/Buffer.hpp>
#include <nta/ntypes/Array.hpp>
#include <nta/types/BasicType.hpp>
#include <nta/engine/Region.hpp>
#include <nta/engine/Spec.hpp>
#include <nta/ntypes/Dimensions.hpp>
#include <nta/ntypes/BundleIO.hpp>
#include <nta/os/FStream.hpp>

namespace nta
{

RegionImpl::RegionImpl(Region *region) :
  region_(region)
{
}

RegionImpl::~RegionImpl()
{
}

// convenience method
const std::string& RegionImpl::getType() const
{
  return region_->getType();
}

const std::string& RegionImpl::getName() const
{
  return region_->getName();
}

const NodeSet& RegionImpl::getEnabledNodes() const
{
  return region_->getEnabledNodes();
}

/* ------------- Parameter support --------------- */
// By default, all typed getParameter calls forward to the
// untyped getParameter that serializes to a buffer

// Use macros to implement these methods.
// This is similar to a template + explicit instantiation, but
// templated methods can't be virtual and thus can't be
// overridden by subclasses.

#define getParameterT(Type) \
Type RegionImpl::getParameter##Type(const std::string& name, Int64 index) \
{\
  if (! region_->getSpec()->parameters.contains(name))     \
    NTA_THROW << "getParameter" #Type ": parameter " << name << " does not exist in nodespec"; \
  ParameterSpec p = region_->getSpec()->parameters.getByName(name); \
  if (p.dataType != NTA_BasicType_ ## Type) \
    NTA_THROW << "getParameter" #Type ": parameter " << name << " is of type " \
              << BasicType::getName(p.dataType) << " not " #Type; \
  WriteBuffer wb; \
  getParameterFromBuffer(name, index, wb); \
  ReadBuffer rb(wb.getData(), wb.getSize(), false /* copy */); \
  Type val; \
  int rc = rb.read(val); \
  if (rc != 0)  \
  { \
    NTA_THROW << "getParameter" #Type " -- failure to get parameter '"  \
              << name << "' on node of type " << getType(); \
  } \
  return val; \
}

getParameterT(Int32);
getParameterT(UInt32);
getParameterT(Int64);
getParameterT(UInt64)
getParameterT(Real32);
getParameterT(Real64);

#define setParameterT(Type) \
void RegionImpl::setParameter##Type(const std::string& name, Int64 index, Type value) \
{ \
  WriteBuffer wb; \
  wb.write((Type)value); \
  ReadBuffer rb(wb.getData(), wb.getSize(), false /* copy */); \
  setParameterFromBuffer(name, index, rb); \
}

setParameterT(Int32);
setParameterT(UInt32);
setParameterT(Int64);
setParameterT(UInt64)
setParameterT(Real32);
setParameterT(Real64);

// buffer mechanism can't handle Handles. RegionImpl must override these methods.
Handle RegionImpl::getParameterHandle(const std::string& name, Int64 index)
{
  NTA_THROW << "Unknown parameter '"  << name << "' of type Handle.";
}

void RegionImpl::setParameterHandle(const std::string& name, Int64 index, Handle h)
{
  NTA_THROW << "Unknown parameter '"  << name << "' of type Handle.";
}

void RegionImpl::getParameterArray(const std::string& name, Int64 index, Array & array)
{
  WriteBuffer wb;
  getParameterFromBuffer(name, index, wb);
  ReadBuffer rb(wb.getData(), wb.getSize(), false /* copy */);
  size_t count = array.getCount();
  void *buffer = array.getBuffer();

  for (size_t i = 0; i < count; i++)
  {
    int rc;
    switch (array.getType())
    {

    case NTA_BasicType_Byte:
      rc = rb.read(((Byte*)buffer)[i]);
      break;
    case NTA_BasicType_Int32:
      rc = rb.read(((Int32*)buffer)[i]);
      break;
    case NTA_BasicType_UInt32:
      rc = rb.read(((UInt32*)buffer)[i]);
      break;
    case NTA_BasicType_Int64:
      rc = rb.read(((Int64*)buffer)[i]);
      break;
    case NTA_BasicType_UInt64:
      rc = rb.read(((UInt64*)buffer)[i]);
      break;
    case NTA_BasicType_Real32:
      rc = rb.read(((Real32*)buffer)[i]);
      break;
    case NTA_BasicType_Real64:
      rc = rb.read(((Real64*)buffer)[i]);
      break;
    default:
      NTA_THROW << "Unsupported basic type " << BasicType::getName(array.getType())
                << " in getParameterArray for parameter " << name;
      break;
    }

    if (rc != 0)
    {
      NTA_THROW << "getParameterArray -- failure to get parameter '"
                << name << "' on node of type " << getType();
    }
  }
  return;
}

void RegionImpl::setParameterArray(const std::string& name, Int64 index,const Array & array)
{
  WriteBuffer wb;
  size_t count = array.getCount();
  void *buffer = array.getBuffer();
  for (size_t i = 0; i < count; i++)
  {
    int rc;
    switch (array.getType())
    {

    case NTA_BasicType_Byte:
      rc = wb.write(((Byte*)buffer)[i]);
      break;
    case NTA_BasicType_Int32:
      rc = wb.write(((Int32*)buffer)[i]);
      break;
    case NTA_BasicType_UInt32:
      rc = wb.write(((UInt32*)buffer)[i]);
      break;
    case NTA_BasicType_Int64:
      rc = wb.write(((Int64*)buffer)[i]);
      break;
    case NTA_BasicType_UInt64:
      rc = wb.write(((UInt64*)buffer)[i]);
      break;
    case NTA_BasicType_Real32:
      rc = wb.write(((Real32*)buffer)[i]);
      break;
    case NTA_BasicType_Real64:
      rc = wb.write(((Real64*)buffer)[i]);
      break;
    default:
      NTA_THROW << "Unsupported basic type " << BasicType::getName(array.getType())
                << " in setParameterArray for parameter " << name;
      break;
    }

    NTA_ASSERT(rc == 0) << "getParameterArray - failure to get parameter '" << name << "' on node of type " << getType();
  }

  ReadBuffer rb(wb.getData(), wb.getSize(), false);
  setParameterFromBuffer(name, index, rb);
}

void RegionImpl::setParameterString(const std::string& name, Int64 index, const std::string& s)
{
  ReadBuffer rb(s.c_str(), s.size(), false);
  setParameterFromBuffer(name, index, rb);
}

std::string RegionImpl::getParameterString(const std::string& name, Int64 index)
{
  WriteBuffer wb;
  getParameterFromBuffer(name, index, wb);
  return std::string(wb.getData(), wb.getSize());
}

// Must be overridden by subclasses
bool RegionImpl::isParameterShared(const std::string& name)
{
  NTA_THROW << "RegionImpl::isParameterShared was not overridden in node type " << getType();
}

void RegionImpl::getParameterFromBuffer(const std::string& name,
                             Int64 index,
                             IWriteBuffer& value)
{
  NTA_THROW << "RegionImpl::getParameterFromBuffer must be overridden by subclasses";
}

void RegionImpl::setParameterFromBuffer(const std::string& name,
                          Int64 index,
                          IReadBuffer& value)
{
  NTA_THROW << "RegionImpl::setParameterFromBuffer must be overridden by subclasses";
}

size_t RegionImpl::getParameterArrayCount(const std::string& name, Int64 index)
{
  // Default implementation for RegionImpls with no array parameters
  // that have a dynamic length.
  //std::map<std::string, ParameterSpec*>::iterator i = nodespec_->parameters.find(name);
  //if (i == nodespec_->parameters.end())

  if (!region_->getSpec()->parameters.contains(name))
  {
    NTA_THROW << "getParameterArrayCount -- no parameter named '"
              << name << "' in node of type " << getType();
  }
  UInt32 count = region_->getSpec()->parameters.getByName(name).count;
  if (count == 0)
  {
    NTA_THROW << "Internal Error -- unknown element count for "
              << "node type " << getType() << ". The RegionImpl "
              << "implementation should override this method.";
  }

  return count;
}

// Provide data access for subclasses

const Input* RegionImpl::getInput(const std::string& name)
{
  return region_->getInput(name);
}

const Output* RegionImpl::getOutput(const std::string& name)
{
  return region_->getOutput(name);
}

const Dimensions& RegionImpl::getDimensions()
{
  return region_->getDimensions();
}

}

<|endoftext|>


<commit_before>/*
 * Copyright (C) 2017 Rhys Ulerich
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 */

#ifndef DESCENDU_SEXP_HPP
#define DESCENDU_SEXP_HPP

#include <cctype>
#include <iostream>
#include <iterator>
#include <sstream>
#include <stdexcept>
#include <string>
#include <utility>

namespace descendu {

namespace sexp {

// TODO Track line/column as input processed
// TODO Record line/column within each node
// Such tracking most useful within stateful parser

enum struct node_type { list=1, symbol, string };

// switch (node.type) {
//     case node_type::list:    /* Use list-like methods */ break;
//     case node_type::symbol:  /* Use node.string */       break;
//     case node_type::string:  /* Use node.string */       break;
// }
class node : std::vector<node>
{
    typedef std::vector<node> base_type;

public:

    // Discern which type of data is contained.
    node_type type;

    // For string node access
    std::string string;

    // For list node access
    using base_type::back;
    using base_type::begin;
    using base_type::cbegin;
    using base_type::cend;
    using base_type::emplace_back;
    using base_type::end;
    using base_type::front;
    using base_type::operator[];
    using base_type::pop_back;
    using base_type::size;

    // Construct a string node
    explicit node(const std::string& s, const bool is_symbol = true)
        : base_type(0)
        , type(is_symbol ? node_type::symbol : node_type::string)
        , string(s)
    {};

    // Move into a string node
    explicit node(std::string&& s, const bool is_symbol = true)
        : base_type(0)
        , type(is_symbol ? node_type::symbol : node_type::string)
        , string(s)
    {};

    // Construct an empty list node
    node()
        : base_type()
        , type(node_type::list)
        , string()
    {};

    bool operator==(const node& other) const {
        if (type != other.type) return false;
        switch (type) {
        case node_type::symbol:
        case node_type::string:
            return string == other.string;
        case node_type::list:
            return static_cast<const base_type&>(*this) == other;
        default:
            throw std::logic_error("Unimplemented case");
        }
    }

    bool operator!=(const node& other) const {
        return !(*this == other);
    }
};

namespace impl {

// Helper to process C99 and S-expression escapes for parse(...) just below
template<typename InputIt>
std::string& append_maybe_escaped(
    const char c,
    std::string &acc,  // Reference!
    InputIt& next,     // Reference!
    InputIt end,
    const bool quoted)
{
    if (c != '\\') return acc += c;
    if (next == end) throw std::invalid_argument("backslash precedes EOF");
    const char q = *next++;
    switch (q) {
    case 'a': return acc += '\a';
    case 'b': return acc += '\b';
    case 'f': return acc += '\f';
    case 'n': return acc += '\n';
    case 'r': return acc += '\r';
    case 't': return acc += '\t';
    case 'v': return acc += '\v';
    case '\'':
    case '\\':
    case '"':
    case '?': return acc += q;
    case 'x':
    case '0': case '1': case '2': case '3': case '4':
    case '5': case '6': case '7': case '8': case '9':
    case 'A': case 'B': case 'C': case 'D': case 'E': case 'F':
        throw new std::logic_error("Escaping via numeric codes unimplemented");
    case '(': case ')': if (!quoted) return acc += q;  // Possibly fall through
    }
    throw new std::invalid_argument(std::string("Improper escape \\") + q);
}

} // namespace impl

// Parse zero or more S-expressions in the input returning a list.
// Notice parsed input is wrapped in one additional list.  That is,
//     1) "(foo)(bar)" returned as ((foo)(bar))
//     2) "(foo)"      returned as ((foo))
//     3) "foo"        returned as (foo)
//     4) ""           returned as ()
// as otherwise non-list or trivial inputs problematic.
// Based upon https://en.wikipedia.org/wiki/S-expression#Parsing
// and grotesquely extended to handle different input with checking.
template<typename InputIt>
node parse(InputIt next, InputIt end) {

    node sexp;
    sexp.emplace_back();
    std::string word;
    int level = 0;
    bool in_string = 0;

    while (next != end) {
        const char c = *next++;
        if (std::isspace(c)) {
            if (in_string) {
                sexp.back().emplace_back(std::move(word));
                word.clear();
            }
            in_string = false;
        } else if (c == '(') {
            ++level;
            sexp.emplace_back();
        } else if (c == ')') {
            if (level == 0) {
                throw std::invalid_argument("unopened right parenthesis");
            }
            if (in_string) {
                sexp.back().emplace_back(std::move(word));
                word.clear();
            }
            in_string = false;
            node temp(std::move(sexp.back()));
            sexp.pop_back();
            sexp.back().emplace_back(std::move(temp));
            --level;
        } else if (c == '"') {
            if (in_string) {
                sexp.back().emplace_back(std::move(word));
                word.clear();
            }
            in_string = false;
            for (;;) {
                if (next == end) throw std::invalid_argument("unclosed quote");
                const char q = *next++;
                if (q == '"') break;
                impl::append_maybe_escaped(q, word, next, end, /*quoted*/true);
            }
            sexp.back().emplace_back(std::move(word), /*string*/false);
            word.clear();
        } else {
            impl::append_maybe_escaped(c, word, next, end, /*quoted*/false);
            in_string = true;
        }
    }

    if (level != 0) {
        throw std::invalid_argument("unclosed left parenthesis");
    }
    if (in_string) { // Required for final top-level string
        sexp.back().emplace_back(word);
    }
    if (!sexp.size()) {
        throw std::logic_error("sanity failure on size");
    }
    if (sexp.front().type != node_type::list) {
        throw std::logic_error("sanity failure on type");
    }

    return sexp.front();
}

node parse(const std::string& in) {
    return parse(in.cbegin(), in.cend());
}

node parse(std::istream& is) {
    return parse(
        std::istream_iterator<char>(is),
        std::istream_iterator<char>());
}

template<typename OutputIterator>
void copy(const node& sexp, OutputIterator out) {
    switch (sexp.type) {
    case node_type::list:
        {
            *out++ = '(';
            std::size_t count = 0;
            for (const auto& term : sexp) {
                if (count++) {
                    *out++ = ' ';
                }
                copy(term, out);
            }
            *out++ = ')';
        }
        break;
    case node_type::symbol:
        for (const char c : sexp.string) {
            switch (c) {
            case '\a': *out++ = '\\'; *out++ = 'a';  break;
            case '\b': *out++ = '\\'; *out++ = 'b';  break;
            case '\f': *out++ = '\\'; *out++ = 'f';  break;
            case '\n': *out++ = '\\'; *out++ = 'n';  break;
            case ' ':  *out++ = '\\'; *out++ = ' ';  break;
            case '?':  *out++ = '\\'; *out++ = '?';  break;
            case '"':  *out++ = '\\'; *out++ = '"';  break;
            case '(':  *out++ = '\\'; *out++ = '(';  break;
            case ')':  *out++ = '\\'; *out++ = ')';  break;
            case '\'': *out++ = '\\'; *out++ = '\''; break;
            case '\\': *out++ = '\\'; *out++ = '\\'; break;
            case '\r': *out++ = '\\'; *out++ = 'r';  break;
            case '\t': *out++ = '\\'; *out++ = 't';  break;
            case '\v': *out++ = '\\'; *out++ = 'v';  break;
            default:
                *out++ = c;
            }
        }
        break;
    case node_type::string:
        *out++ = '"';
        for (const char c : sexp.string) {
            switch (c) {
            case '\a': *out++ = '\\'; *out++ = 'a';  break;
            case '\b': *out++ = '\\'; *out++ = 'b';  break;
            case '\f': *out++ = '\\'; *out++ = 'f';  break;
            case '"':  *out++ = '\\'; *out++ = '"';  break;
            case '\\': *out++ = '\\'; *out++ = '\\'; break;
            default:
                *out++ = c;
            }
        }
        *out++ = '"';
        break;
    default:
        throw std::logic_error("Unimplemented case");
    }
}

void copy(const node& sexp, std::ostream& os) {
    return copy(sexp, std::ostream_iterator<char>(os));
}

std::string to_string(const node& sexp) {
    std::ostringstream oss;
    std::ostream_iterator<char> it(oss);
    copy(sexp, it);
    return oss.str();
}

} // namespace

} // namespace

#endif
<commit_msg>Require bounds check<commit_after>/*
 * Copyright (C) 2017 Rhys Ulerich
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 */

#ifndef DESCENDU_SEXP_HPP
#define DESCENDU_SEXP_HPP

#include <cctype>
#include <iostream>
#include <iterator>
#include <sstream>
#include <stdexcept>
#include <string>
#include <utility>

namespace descendu {

namespace sexp {

// TODO Track line/column as input processed
// TODO Record line/column within each node
// Such tracking most useful within stateful parser

enum struct node_type { list=1, symbol, string };

// switch (node.type) {
//     case node_type::list:    /* Use list-like methods */ break;
//     case node_type::symbol:  /* Use node.string */       break;
//     case node_type::string:  /* Use node.string */       break;
// }
class node : std::vector<node>
{
    typedef std::vector<node> base_type;

public:

    // Discern which type of data is contained.
    node_type type;

    // For string node access
    std::string string;

    // For list node access
    using base_type::at;
    using base_type::back;
    using base_type::begin;
    using base_type::cbegin;
    using base_type::cend;
    using base_type::emplace_back;
    using base_type::end;
    using base_type::front;
    using base_type::pop_back;
    using base_type::size;

    // Construct a string node
    explicit node(const std::string& s, const bool is_symbol = true)
        : base_type(0)
        , type(is_symbol ? node_type::symbol : node_type::string)
        , string(s)
    {};

    // Move into a string node
    explicit node(std::string&& s, const bool is_symbol = true)
        : base_type(0)
        , type(is_symbol ? node_type::symbol : node_type::string)
        , string(s)
    {};

    // Construct an empty list node
    node()
        : base_type()
        , type(node_type::list)
        , string()
    {};

    bool operator==(const node& other) const {
        if (type != other.type) return false;
        switch (type) {
        case node_type::symbol:
        case node_type::string:
            return string == other.string;
        case node_type::list:
            return static_cast<const base_type&>(*this) == other;
        default:
            throw std::logic_error("Unimplemented case");
        }
    }

    bool operator!=(const node& other) const {
        return !(*this == other);
    }
};

namespace impl {

// Helper to process C99 and S-expression escapes for parse(...) just below
template<typename InputIt>
std::string& append_maybe_escaped(
    const char c,
    std::string &acc,  // Reference!
    InputIt& next,     // Reference!
    InputIt end,
    const bool quoted)
{
    if (c != '\\') return acc += c;
    if (next == end) throw std::invalid_argument("backslash precedes EOF");
    const char q = *next++;
    switch (q) {
    case 'a': return acc += '\a';
    case 'b': return acc += '\b';
    case 'f': return acc += '\f';
    case 'n': return acc += '\n';
    case 'r': return acc += '\r';
    case 't': return acc += '\t';
    case 'v': return acc += '\v';
    case '\'':
    case '\\':
    case '"':
    case '?': return acc += q;
    case 'x':
    case '0': case '1': case '2': case '3': case '4':
    case '5': case '6': case '7': case '8': case '9':
    case 'A': case 'B': case 'C': case 'D': case 'E': case 'F':
        throw new std::logic_error("Escaping via numeric codes unimplemented");
    case '(': case ')': if (!quoted) return acc += q;  // Possibly fall through
    }
    throw new std::invalid_argument(std::string("Improper escape \\") + q);
}

} // namespace impl

// Parse zero or more S-expressions in the input returning a list.
// Notice parsed input is wrapped in one additional list.  That is,
//     1) "(foo)(bar)" returned as ((foo)(bar))
//     2) "(foo)"      returned as ((foo))
//     3) "foo"        returned as (foo)
//     4) ""           returned as ()
// as otherwise non-list or trivial inputs problematic.
// Based upon https://en.wikipedia.org/wiki/S-expression#Parsing
// and grotesquely extended to handle different input with checking.
template<typename InputIt>
node parse(InputIt next, InputIt end) {

    node sexp;
    sexp.emplace_back();
    std::string word;
    int level = 0;
    bool in_string = 0;

    while (next != end) {
        const char c = *next++;
        if (std::isspace(c)) {
            if (in_string) {
                sexp.back().emplace_back(std::move(word));
                word.clear();
            }
            in_string = false;
        } else if (c == '(') {
            ++level;
            sexp.emplace_back();
        } else if (c == ')') {
            if (level == 0) {
                throw std::invalid_argument("unopened right parenthesis");
            }
            if (in_string) {
                sexp.back().emplace_back(std::move(word));
                word.clear();
            }
            in_string = false;
            node temp(std::move(sexp.back()));
            sexp.pop_back();
            sexp.back().emplace_back(std::move(temp));
            --level;
        } else if (c == '"') {
            if (in_string) {
                sexp.back().emplace_back(std::move(word));
                word.clear();
            }
            in_string = false;
            for (;;) {
                if (next == end) throw std::invalid_argument("unclosed quote");
                const char q = *next++;
                if (q == '"') break;
                impl::append_maybe_escaped(q, word, next, end, /*quoted*/true);
            }
            sexp.back().emplace_back(std::move(word), /*string*/false);
            word.clear();
        } else {
            impl::append_maybe_escaped(c, word, next, end, /*quoted*/false);
            in_string = true;
        }
    }

    if (level != 0) {
        throw std::invalid_argument("unclosed left parenthesis");
    }
    if (in_string) { // Required for final top-level string
        sexp.back().emplace_back(word);
    }
    if (!sexp.size()) {
        throw std::logic_error("sanity failure on size");
    }
    if (sexp.front().type != node_type::list) {
        throw std::logic_error("sanity failure on type");
    }

    return sexp.front();
}

node parse(const std::string& in) {
    return parse(in.cbegin(), in.cend());
}

node parse(std::istream& is) {
    return parse(
        std::istream_iterator<char>(is),
        std::istream_iterator<char>());
}

template<typename OutputIterator>
void copy(const node& sexp, OutputIterator out) {
    switch (sexp.type) {
    case node_type::list:
        {
            *out++ = '(';
            std::size_t count = 0;
            for (const auto& term : sexp) {
                if (count++) {
                    *out++ = ' ';
                }
                copy(term, out);
            }
            *out++ = ')';
        }
        break;
    case node_type::symbol:
        for (const char c : sexp.string) {
            switch (c) {
            case '\a': *out++ = '\\'; *out++ = 'a';  break;
            case '\b': *out++ = '\\'; *out++ = 'b';  break;
            case '\f': *out++ = '\\'; *out++ = 'f';  break;
            case '\n': *out++ = '\\'; *out++ = 'n';  break;
            case ' ':  *out++ = '\\'; *out++ = ' ';  break;
            case '?':  *out++ = '\\'; *out++ = '?';  break;
            case '"':  *out++ = '\\'; *out++ = '"';  break;
            case '(':  *out++ = '\\'; *out++ = '(';  break;
            case ')':  *out++ = '\\'; *out++ = ')';  break;
            case '\'': *out++ = '\\'; *out++ = '\''; break;
            case '\\': *out++ = '\\'; *out++ = '\\'; break;
            case '\r': *out++ = '\\'; *out++ = 'r';  break;
            case '\t': *out++ = '\\'; *out++ = 't';  break;
            case '\v': *out++ = '\\'; *out++ = 'v';  break;
            default:
                *out++ = c;
            }
        }
        break;
    case node_type::string:
        *out++ = '"';
        for (const char c : sexp.string) {
            switch (c) {
            case '\a': *out++ = '\\'; *out++ = 'a';  break;
            case '\b': *out++ = '\\'; *out++ = 'b';  break;
            case '\f': *out++ = '\\'; *out++ = 'f';  break;
            case '"':  *out++ = '\\'; *out++ = '"';  break;
            case '\\': *out++ = '\\'; *out++ = '\\'; break;
            default:
                *out++ = c;
            }
        }
        *out++ = '"';
        break;
    default:
        throw std::logic_error("Unimplemented case");
    }
}

void copy(const node& sexp, std::ostream& os) {
    return copy(sexp, std::ostream_iterator<char>(os));
}

std::string to_string(const node& sexp) {
    std::ostringstream oss;
    std::ostream_iterator<char> it(oss);
    copy(sexp, it);
    return oss.str();
}

} // namespace

} // namespace

#endif
<|endoftext|>


<commit_before>#include "pch.h"
#include "jnc_Function.h"
#include "jnc_Module.h"
#include "jnc_ClassType.h"
#include "jnc_Parser.llk.h"

namespace jnc {

//.............................................................................

const char*
GetFunctionKindString (EFunction FunctionKind)
{
	static const char* StringTable [EFunction__Count] =
	{
		"undefined-function-kind",  // EFunction_Undefined,
		"named-function",           // EFunction_Named,
		"get",                      // EFunction_Getter,
		"set",                      // EFunction_Setter,
		"bind",                     // EFunction_Binder,
		"prime",                    // EFunction_Primer,
		"preconstruct",             // EFunction_PreConstructor,
		"construct",                // EFunction_Constructor,
		"destruct",                 // EFunction_Destructor,
		"static construct",         // EFunction_StaticConstructor,
		"static destruct",          // EFunction_StaticDestructor,
		"module construct",         // EFunction_ModuleConstructor,
		"module destruct",          // EFunction_ModuleDestructor,
		"call-operator",            // EFunction_CallOperator,
		"cast-operator",            // EFunction_CastOperator,
		"unary-operator",           // EFunction_UnaryOperator,
		"binary-operator",          // EFunction_BinaryOperator,
		"operator-new",             // EFunction_OperatorNew,
		"internal",                 // EFunction_Internal,
		"thunk",                    // EFunction_Thunk,
		"reaction",                 // EFunction_Reaction,
		"schedule-launcher",        // EFunction_ScheduleLauncher,
	};

	return (size_t) FunctionKind < EFunction__Count ?
		StringTable [FunctionKind] :
		StringTable [EFunction_Undefined];
}

//.............................................................................

int
GetFunctionKindFlags (EFunction FunctionKind)
{
	static int FlagTable [EFunction__Count] =
	{
		0,                              // EFunction_Undefined,
		0,                              // EFunction_Named,
		EFunctionKindFlag_NoOverloads,  // EFunction_Getter,
		0,                              // EFunction_Setter,
		0,                              // EFunction_Binder,
		0,                              // EFunction_Primer,
		EFunctionKindFlag_NoStorage   | // EFunction_PreConstructor,
		EFunctionKindFlag_NoOverloads |
		EFunctionKindFlag_NoArgs,
		EFunctionKindFlag_NoStorage,    // EFunction_Constructor,
		EFunctionKindFlag_NoStorage   | // EFunction_Destructor,
		EFunctionKindFlag_NoOverloads |
		EFunctionKindFlag_NoArgs,
		EFunctionKindFlag_NoStorage   | // EFunction_StaticConstructor,
		EFunctionKindFlag_NoOverloads |
		EFunctionKindFlag_NoArgs,
		EFunctionKindFlag_NoStorage   | // EFunction_StaticDestructor,
		EFunctionKindFlag_NoOverloads |
		EFunctionKindFlag_NoArgs,
		EFunctionKindFlag_NoStorage   | // EFunction_ModuleConstructor,
		EFunctionKindFlag_NoOverloads |
		EFunctionKindFlag_NoArgs,
		EFunctionKindFlag_NoStorage   | // EFunction_ModuleDestructor,
		EFunctionKindFlag_NoOverloads |
		EFunctionKindFlag_NoArgs,
		0,                              // EFunction_CallOperator,
		EFunctionKindFlag_NoOverloads | // EFunction_CastOperator,
		EFunctionKindFlag_NoArgs,
		EFunctionKindFlag_NoOverloads | // EFunction_UnaryOperator,
		EFunctionKindFlag_NoArgs,
		0,                              // EFunction_BinaryOperator,
		0,                              // EFunction_OperatorNew,
		0,                              // EFunction_Internal,
		0,                              // EFunction_Thunk,
		0,                              // EFunction_Reaction,
		0,                              // EFunction_ScheduleLauncher,
	};

	return FunctionKind >= 0 && FunctionKind < EFunction__Count ? FlagTable [FunctionKind] : 0;
}

//.............................................................................

CFunction::CFunction ()
{
	m_ItemKind = EModuleItem_Function;
	m_FunctionKind = EFunction_Undefined;
	m_pType = NULL;
	m_pCastOpType = NULL;
	m_pThisArgType = NULL;
	m_pThisType = NULL;
	m_ThisArgDelta = 0;
	m_ThisArgTypeFlags = 0;
	m_pVirtualOriginClassType = NULL;
	m_pProperty = NULL;
	m_ClassVTableIndex = -1;
	m_PropertyVTableIndex = -1;
	m_pEntryBlock = NULL;
	m_pScope = NULL;
	m_pLlvmFunction = NULL;
	m_pLlvmPostTlsPrologueInst = NULL;
	m_pfMachineCode = NULL;
	m_MachineCodeSize = 0;
}

void
CFunction::MarkGc ()
{
	llvm::Function* pLlvmFunction = GetLlvmFunction ();
	if (!pLlvmFunction->hasGC ())
		pLlvmFunction->setGC ("jnc-shadow-stack");
}

bool
CFunction::SetBody (rtl::CBoxListT <CToken>* pTokenList)
{
	if (!m_Body.IsEmpty ())
	{
		err::SetFormatStringError ("'%s' already has a body", m_Tag.cc ());
		return false;
	}

	if (m_StorageKind == EStorage_Abstract)
	{
		err::SetFormatStringError ("'%s' is abstract and hence cannot have a body", m_Tag.cc ());
		return false;
	}

	m_Body.TakeOver (pTokenList);
	m_pModule->MarkForCompile (this);
	return true;
}

llvm::Function*
CFunction::GetLlvmFunction ()
{
	if (m_pLlvmFunction)
		return m_pLlvmFunction;

	m_pLlvmFunction = m_pType->GetCallConv ()->CreateLlvmFunction (m_pType, m_Tag);
	m_pModule->m_FunctionMgr.m_LlvmFunctionMap [m_pLlvmFunction] = this;
	return m_pLlvmFunction;
}

llvm::DISubprogram
CFunction::GetLlvmDiSubprogram ()
{
	if (m_LlvmDiSubprogram)
		return m_LlvmDiSubprogram;

	m_LlvmDiSubprogram = m_pModule->m_LlvmDiBuilder.CreateFunction (this);
	return m_LlvmDiSubprogram;
}

void
CFunction::ConvertToMemberMethod (CNamedType* pParentType)
{
	ASSERT (m_TypeOverload.GetOverloadCount () == 1);

	m_pParentNamespace = pParentType;
	m_pType = pParentType->GetMemberMethodType (m_pType, m_ThisArgTypeFlags);
	m_TypeOverload = m_pType;

	ASSERT (!m_pType->GetArgArray ().IsEmpty ());
	m_pThisArgType = m_pType->GetArgArray () [0]->GetType ();
	m_pThisType = m_pThisArgType;
}

bool
CFunction::AddOverload (CFunction* pFunction)
{
	bool Result = m_TypeOverload.AddOverload (pFunction->m_pType);
	if (!Result)
		return false;

	m_OverloadArray.Append (pFunction);
	return true;
}

void
CFunction::AddTlsVariable (CVariable* pVariable)
{
	llvm::AllocaInst* pLlvmAlloca = (llvm::AllocaInst*) pVariable->GetLlvmValue ();
	ASSERT (pLlvmAlloca && llvm::isa <llvm::AllocaInst> (*pLlvmAlloca));

	TTlsVariable TlsVariable;
	TlsVariable.m_pVariable = pVariable;
	TlsVariable.m_pLlvmAlloca = pLlvmAlloca;
	m_TlsVariableArray.Append (TlsVariable);
}

bool
CFunction::Compile ()
{
	ASSERT (!m_Body.IsEmpty ()); // otherwise what are we doing here?
	ASSERT (!m_pEntryBlock || m_FunctionKind == EFunction_ModuleConstructor);

	bool Result;

	if (m_pEntryBlock) // already compiled
		return true;

	m_pModule->m_UnitMgr.SetCurrentUnit (m_pItemDecl->GetParentUnit ());

	// prologue

	CToken::CPos BeginPos = m_Body.GetHead ()->m_Pos;
	CToken::CPos EndPos = m_Body.GetTail ()->m_Pos;

	Result = m_pModule->m_FunctionMgr.Prologue (this, BeginPos);
	if (!Result)
		return false;

	TOnceStmt Stmt; // for static constructors

	// parse body

	CParser Parser;
	Parser.m_pModule = m_pModule;
	Parser.m_Stage = CParser::EStage_Pass2;

	ESymbol StartSymbol = ESymbol_compound_stmt;

	if (m_FunctionKind == EFunction_StaticConstructor)
	{
		CDerivableType* pParentType = GetParentType ();
		if (!pParentType)
		{
			err::SetFormatStringError ("static constructors for properties are not yet supported");
			return false;
		}

		m_pModule->m_ControlFlowMgr.OnceStmt_Create (&Stmt, pParentType->GetStaticOnceFlagVariable ());

		Result = m_pModule->m_ControlFlowMgr.OnceStmt_PreBody (&Stmt, BeginPos);
		if (!Result)
			return false;
	}
	else if (m_FunctionKind == EFunction_PreConstructor)
	{
		CDerivableType* pParentType = GetParentType ();
		if (!pParentType)
		{
			err::SetFormatStringError ("preconstructors for properties are not yet supported");
			return false;
		}

		CFunction* pStaticConstructor = pParentType->GetStaticConstructor ();
		if (pStaticConstructor)
			m_pModule->m_OperatorMgr.CallOperator (pStaticConstructor);

		CValue ThisValue = m_pModule->m_FunctionMgr.GetThisValue ();
		ASSERT (ThisValue);

		EType TypeKind = pParentType->GetTypeKind ();
		switch (TypeKind)
		{
		case EType_Struct:
			Result = ((CStructType*) pParentType)->InitializeFields (ThisValue);
			break;

		case EType_Union:
			Result = ((CUnionType*) pParentType)->InitializeField (ThisValue);
			break;

		case EType_Class:
			Result = ((CClassType*) pParentType)->GetIfaceStructType ()->InitializeFields (ThisValue);
			break;
		}
	}
	else if (m_FunctionKind == EFunction_Constructor)
	{
		StartSymbol = ESymbol_constructor_compound_stmt;

		ENamespace Namespace = m_pParentNamespace->GetNamespaceKind ();
		ASSERT (Namespace == ENamespace_Type || Namespace == ENamespace_Property);

		if (Namespace == ENamespace_Type)
			Parser.m_pConstructorType = (CDerivableType*) m_pParentNamespace;
		else
			Parser.m_pConstructorProperty = (CProperty*) m_pParentNamespace;
	}

	Result = Parser.ParseTokenList (StartSymbol, m_Body, true);
	if (!Result)
		return false;

	if (m_FunctionKind == EFunction_StaticConstructor)
		m_pModule->m_ControlFlowMgr.OnceStmt_PostBody (&Stmt, EndPos);

	// epilogue

	m_pModule->m_NamespaceMgr.SetSourcePos (EndPos);

	Result = m_pModule->m_FunctionMgr.Epilogue ();
	if (!Result)
		return false;

	return true;
}

//.............................................................................

CModuleItem*
CLazyStdFunction::GetActualItem ()
{
	return m_pModule->m_FunctionMgr.GetStdFunction (m_Func);
}

//.............................................................................

} // namespace jnc {
<commit_msg>[jancy] function tagging critucal temp-fix (operator-new -> operator_new)<commit_after>#include "pch.h"
#include "jnc_Function.h"
#include "jnc_Module.h"
#include "jnc_ClassType.h"
#include "jnc_Parser.llk.h"

namespace jnc {

//.............................................................................

const char*
GetFunctionKindString (EFunction FunctionKind)
{
	static const char* StringTable [EFunction__Count] =
	{
		"undefined-function-kind",  // EFunction_Undefined,
		"named-function",           // EFunction_Named,
		"get",                      // EFunction_Getter,
		"set",                      // EFunction_Setter,
		"bind",                     // EFunction_Binder,
		"prime",                    // EFunction_Primer,
		"preconstruct",             // EFunction_PreConstructor,
		"construct",                // EFunction_Constructor,
		"destruct",                 // EFunction_Destructor,
		"static construct",         // EFunction_StaticConstructor,
		"static destruct",          // EFunction_StaticDestructor,
		"module construct",         // EFunction_ModuleConstructor,
		"module destruct",          // EFunction_ModuleDestructor,
		"call-operator",            // EFunction_CallOperator,
		"cast-operator",            // EFunction_CastOperator,
		"unary-operator",           // EFunction_UnaryOperator,
		"binary-operator",          // EFunction_BinaryOperator,
		"operator_new",             // EFunction_OperatorNew,
		"internal",                 // EFunction_Internal,
		"thunk",                    // EFunction_Thunk,
		"reaction",                 // EFunction_Reaction,
		"schedule-launcher",        // EFunction_ScheduleLauncher,
	};

	return (size_t) FunctionKind < EFunction__Count ?
		StringTable [FunctionKind] :
		StringTable [EFunction_Undefined];
}

//.............................................................................

int
GetFunctionKindFlags (EFunction FunctionKind)
{
	static int FlagTable [EFunction__Count] =
	{
		0,                              // EFunction_Undefined,
		0,                              // EFunction_Named,
		EFunctionKindFlag_NoOverloads,  // EFunction_Getter,
		0,                              // EFunction_Setter,
		0,                              // EFunction_Binder,
		0,                              // EFunction_Primer,
		EFunctionKindFlag_NoStorage   | // EFunction_PreConstructor,
		EFunctionKindFlag_NoOverloads |
		EFunctionKindFlag_NoArgs,
		EFunctionKindFlag_NoStorage,    // EFunction_Constructor,
		EFunctionKindFlag_NoStorage   | // EFunction_Destructor,
		EFunctionKindFlag_NoOverloads |
		EFunctionKindFlag_NoArgs,
		EFunctionKindFlag_NoStorage   | // EFunction_StaticConstructor,
		EFunctionKindFlag_NoOverloads |
		EFunctionKindFlag_NoArgs,
		EFunctionKindFlag_NoStorage   | // EFunction_StaticDestructor,
		EFunctionKindFlag_NoOverloads |
		EFunctionKindFlag_NoArgs,
		EFunctionKindFlag_NoStorage   | // EFunction_ModuleConstructor,
		EFunctionKindFlag_NoOverloads |
		EFunctionKindFlag_NoArgs,
		EFunctionKindFlag_NoStorage   | // EFunction_ModuleDestructor,
		EFunctionKindFlag_NoOverloads |
		EFunctionKindFlag_NoArgs,
		0,                              // EFunction_CallOperator,
		EFunctionKindFlag_NoOverloads | // EFunction_CastOperator,
		EFunctionKindFlag_NoArgs,
		EFunctionKindFlag_NoOverloads | // EFunction_UnaryOperator,
		EFunctionKindFlag_NoArgs,
		0,                              // EFunction_BinaryOperator,
		0,                              // EFunction_OperatorNew,
		0,                              // EFunction_Internal,
		0,                              // EFunction_Thunk,
		0,                              // EFunction_Reaction,
		0,                              // EFunction_ScheduleLauncher,
	};

	return FunctionKind >= 0 && FunctionKind < EFunction__Count ? FlagTable [FunctionKind] : 0;
}

//.............................................................................

CFunction::CFunction ()
{
	m_ItemKind = EModuleItem_Function;
	m_FunctionKind = EFunction_Undefined;
	m_pType = NULL;
	m_pCastOpType = NULL;
	m_pThisArgType = NULL;
	m_pThisType = NULL;
	m_ThisArgDelta = 0;
	m_ThisArgTypeFlags = 0;
	m_pVirtualOriginClassType = NULL;
	m_pProperty = NULL;
	m_ClassVTableIndex = -1;
	m_PropertyVTableIndex = -1;
	m_pEntryBlock = NULL;
	m_pScope = NULL;
	m_pLlvmFunction = NULL;
	m_pLlvmPostTlsPrologueInst = NULL;
	m_pfMachineCode = NULL;
	m_MachineCodeSize = 0;
}

void
CFunction::MarkGc ()
{
	llvm::Function* pLlvmFunction = GetLlvmFunction ();
	if (!pLlvmFunction->hasGC ())
		pLlvmFunction->setGC ("jnc-shadow-stack");
}

bool
CFunction::SetBody (rtl::CBoxListT <CToken>* pTokenList)
{
	if (!m_Body.IsEmpty ())
	{
		err::SetFormatStringError ("'%s' already has a body", m_Tag.cc ());
		return false;
	}

	if (m_StorageKind == EStorage_Abstract)
	{
		err::SetFormatStringError ("'%s' is abstract and hence cannot have a body", m_Tag.cc ());
		return false;
	}

	m_Body.TakeOver (pTokenList);
	m_pModule->MarkForCompile (this);
	return true;
}

llvm::Function*
CFunction::GetLlvmFunction ()
{
	if (m_pLlvmFunction)
		return m_pLlvmFunction;

	m_pLlvmFunction = m_pType->GetCallConv ()->CreateLlvmFunction (m_pType, m_Tag);
	m_pModule->m_FunctionMgr.m_LlvmFunctionMap [m_pLlvmFunction] = this;
	return m_pLlvmFunction;
}

llvm::DISubprogram
CFunction::GetLlvmDiSubprogram ()
{
	if (m_LlvmDiSubprogram)
		return m_LlvmDiSubprogram;

	m_LlvmDiSubprogram = m_pModule->m_LlvmDiBuilder.CreateFunction (this);
	return m_LlvmDiSubprogram;
}

void
CFunction::ConvertToMemberMethod (CNamedType* pParentType)
{
	ASSERT (m_TypeOverload.GetOverloadCount () == 1);

	m_pParentNamespace = pParentType;
	m_pType = pParentType->GetMemberMethodType (m_pType, m_ThisArgTypeFlags);
	m_TypeOverload = m_pType;

	ASSERT (!m_pType->GetArgArray ().IsEmpty ());
	m_pThisArgType = m_pType->GetArgArray () [0]->GetType ();
	m_pThisType = m_pThisArgType;
}

bool
CFunction::AddOverload (CFunction* pFunction)
{
	bool Result = m_TypeOverload.AddOverload (pFunction->m_pType);
	if (!Result)
		return false;

	m_OverloadArray.Append (pFunction);
	return true;
}

void
CFunction::AddTlsVariable (CVariable* pVariable)
{
	llvm::AllocaInst* pLlvmAlloca = (llvm::AllocaInst*) pVariable->GetLlvmValue ();
	ASSERT (pLlvmAlloca && llvm::isa <llvm::AllocaInst> (*pLlvmAlloca));

	TTlsVariable TlsVariable;
	TlsVariable.m_pVariable = pVariable;
	TlsVariable.m_pLlvmAlloca = pLlvmAlloca;
	m_TlsVariableArray.Append (TlsVariable);
}

bool
CFunction::Compile ()
{
	ASSERT (!m_Body.IsEmpty ()); // otherwise what are we doing here?
	ASSERT (!m_pEntryBlock || m_FunctionKind == EFunction_ModuleConstructor);

	bool Result;

	if (m_pEntryBlock) // already compiled
		return true;

	m_pModule->m_UnitMgr.SetCurrentUnit (m_pItemDecl->GetParentUnit ());

	// prologue

	CToken::CPos BeginPos = m_Body.GetHead ()->m_Pos;
	CToken::CPos EndPos = m_Body.GetTail ()->m_Pos;

	Result = m_pModule->m_FunctionMgr.Prologue (this, BeginPos);
	if (!Result)
		return false;

	TOnceStmt Stmt; // for static constructors

	// parse body

	CParser Parser;
	Parser.m_pModule = m_pModule;
	Parser.m_Stage = CParser::EStage_Pass2;

	ESymbol StartSymbol = ESymbol_compound_stmt;

	if (m_FunctionKind == EFunction_StaticConstructor)
	{
		CDerivableType* pParentType = GetParentType ();
		if (!pParentType)
		{
			err::SetFormatStringError ("static constructors for properties are not yet supported");
			return false;
		}

		m_pModule->m_ControlFlowMgr.OnceStmt_Create (&Stmt, pParentType->GetStaticOnceFlagVariable ());

		Result = m_pModule->m_ControlFlowMgr.OnceStmt_PreBody (&Stmt, BeginPos);
		if (!Result)
			return false;
	}
	else if (m_FunctionKind == EFunction_PreConstructor)
	{
		CDerivableType* pParentType = GetParentType ();
		if (!pParentType)
		{
			err::SetFormatStringError ("preconstructors for properties are not yet supported");
			return false;
		}

		CFunction* pStaticConstructor = pParentType->GetStaticConstructor ();
		if (pStaticConstructor)
			m_pModule->m_OperatorMgr.CallOperator (pStaticConstructor);

		CValue ThisValue = m_pModule->m_FunctionMgr.GetThisValue ();
		ASSERT (ThisValue);

		EType TypeKind = pParentType->GetTypeKind ();
		switch (TypeKind)
		{
		case EType_Struct:
			Result = ((CStructType*) pParentType)->InitializeFields (ThisValue);
			break;

		case EType_Union:
			Result = ((CUnionType*) pParentType)->InitializeField (ThisValue);
			break;

		case EType_Class:
			Result = ((CClassType*) pParentType)->GetIfaceStructType ()->InitializeFields (ThisValue);
			break;
		}
	}
	else if (m_FunctionKind == EFunction_Constructor)
	{
		StartSymbol = ESymbol_constructor_compound_stmt;

		ENamespace Namespace = m_pParentNamespace->GetNamespaceKind ();
		ASSERT (Namespace == ENamespace_Type || Namespace == ENamespace_Property);

		if (Namespace == ENamespace_Type)
			Parser.m_pConstructorType = (CDerivableType*) m_pParentNamespace;
		else
			Parser.m_pConstructorProperty = (CProperty*) m_pParentNamespace;
	}

	Result = Parser.ParseTokenList (StartSymbol, m_Body, true);
	if (!Result)
		return false;

	if (m_FunctionKind == EFunction_StaticConstructor)
		m_pModule->m_ControlFlowMgr.OnceStmt_PostBody (&Stmt, EndPos);

	// epilogue

	m_pModule->m_NamespaceMgr.SetSourcePos (EndPos);

	Result = m_pModule->m_FunctionMgr.Epilogue ();
	if (!Result)
		return false;

	return true;
}

//.............................................................................

CModuleItem*
CLazyStdFunction::GetActualItem ()
{
	return m_pModule->m_FunctionMgr.GetStdFunction (m_Func);
}

//.............................................................................

} // namespace jnc {
<|endoftext|>


<commit_before>/*
 * pv_example.cpp
 *
 *  Example of a PetaVision application.
 *
 */

#include <stdlib.h>

#include "include/pv_common.h"
#include "columns/HyPerCol.hpp"

#include "layers/Image.hpp"
#include "layers/Retina.hpp"
#include "layers/LIF.hpp"

using namespace PV;

int main(int argc, char* argv[])
{
   HyPerCol * hc = new HyPerCol("column", argc, argv);

   // construct layers
   Image * image = new Image("Image", hc, hc->inputFile());
   HyPerLayer * retina  = new Retina("Retina", hc);
   HyPerLayer * l1      = new LIF("L1", hc);

   // connect the layers
   new PV::HyPerConn("Retina to L1", hc, retina, l1, CHANNEL_EXC);

   // finish initialization now that everything is connected
   hc->initFinish();

   // run the simulation for 2 time steps
   hc->run(1);

   // clean up (HyPerCol owns the layers, so don't delete them here)
   delete hc;

   return 0;
}

<commit_msg>Added path variable to HyPerCon constructor so that OpenCL app can find the kernels.<commit_after>/*
 * pv_example.cpp
 *
 *  Example of a PetaVision application.
 *
 */

#include <stdlib.h>

#include "include/pv_common.h"
#include "columns/HyPerCol.hpp"

#include "layers/Image.hpp"
#include "layers/Retina.hpp"
#include "layers/LIF.hpp"

using namespace PV;

int main(int argc, char* argv[])
{
   HyPerCol * hc = new HyPerCol("column", argc, argv, ".");

   // construct layers
   Image * image = new Image("Image", hc, hc->inputFile());
   HyPerLayer * retina  = new Retina("Retina", hc);
   HyPerLayer * l1      = new LIF("L1", hc);

   // connect the layers
   new PV::HyPerConn("Retina to L1", hc, retina, l1, CHANNEL_EXC);

   // finish initialization now that everything is connected
   hc->initFinish();

   // run the simulation for 2 time steps
   hc->run(1);

   // clean up (HyPerCol owns the layers, so don't delete them here)
   delete hc;

   return 0;
}

<|endoftext|>


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

#include "base/file_util.h"
#include "base/path_service.h"
#include "base/test/test_timeouts.h"
#include "build/build_config.h"
#include "chrome/common/chrome_switches.h"
#include "chrome/test/automation/tab_proxy.h"
#include "chrome/test/ui/ui_test.h"
#include "net/base/net_util.h"
#include "net/test/test_server.h"
#include "webkit/plugins/plugin_switches.h"

namespace {

// Platform-specific filename relative to the chrome executable.
#if defined(OS_WIN)
const wchar_t library_name[] = L"ppapi_tests.dll";
#elif defined(OS_MACOSX)
const char library_name[] = "ppapi_tests.plugin";
#elif defined(OS_POSIX)
const char library_name[] = "libppapi_tests.so";
#endif

}  // namespace

class PPAPITest : public UITest {
 public:
  PPAPITest() {
    // Append the switch to register the pepper plugin.
    // library name = <out dir>/<test_name>.<library_extension>
    // MIME type = application/x-ppapi-<test_name>
    FilePath plugin_dir;
    PathService::Get(base::DIR_EXE, &plugin_dir);

    FilePath plugin_lib = plugin_dir.Append(library_name);
    EXPECT_TRUE(file_util::PathExists(plugin_lib));
    FilePath::StringType pepper_plugin = plugin_lib.value();
    pepper_plugin.append(FILE_PATH_LITERAL(";application/x-ppapi-tests"));
    launch_arguments_.AppendSwitchNative(switches::kRegisterPepperPlugins,
                                         pepper_plugin);

    // The test sends us the result via a cookie.
    launch_arguments_.AppendSwitch(switches::kEnableFileCookies);

    // Some stuff is hung off of the testing interface which is not enabled
    // by default.
    launch_arguments_.AppendSwitch(switches::kEnablePepperTesting);

    // Give unlimited quota for files to Pepper tests.
    // TODO(dumi): remove this switch once we have a quota management
    // system in place.
    launch_arguments_.AppendSwitch(switches::kUnlimitedQuotaForFiles);

#if defined(ENABLE_P2P_APIS)
    // Enable P2P API.
    launch_arguments_.AppendSwitch(switches::kEnableP2PApi);
#endif // ENABLE_P2P_APIS
  }

  void RunTest(const std::string& test_case) {
    FilePath test_path;
    PathService::Get(base::DIR_SOURCE_ROOT, &test_path);
    test_path = test_path.Append(FILE_PATH_LITERAL("ppapi"));
    test_path = test_path.Append(FILE_PATH_LITERAL("tests"));
    test_path = test_path.Append(FILE_PATH_LITERAL("test_case.html"));

    // Sanity check the file name.
    EXPECT_TRUE(file_util::PathExists(test_path));

    GURL::Replacements replacements;
    std::string query("testcase=");
    query += test_case;
    replacements.SetQuery(query.c_str(), url_parse::Component(0, query.size()));
    GURL test_url = net::FilePathToFileURL(test_path);
    RunTestURL(test_url.ReplaceComponents(replacements));
  }

  void RunTestViaHTTP(const std::string& test_case) {
    net::TestServer test_server(
        net::TestServer::TYPE_HTTP,
        FilePath(FILE_PATH_LITERAL("ppapi/tests")));
    ASSERT_TRUE(test_server.Start());
    RunTestURL(
        test_server.GetURL("files/test_case.html?testcase=" + test_case));
  }

 private:
  void RunTestURL(const GURL& test_url) {
    scoped_refptr<TabProxy> tab(GetActiveTab());
    ASSERT_TRUE(tab.get());
    ASSERT_TRUE(tab->NavigateToURL(test_url));

    // First wait for the "starting" signal. This cookie is set at the start
    // of every test. Waiting for this separately allows us to avoid a single
    // long timeout. Instead, we can have two timeouts which allow startup +
    // test execution time to take a while on a loaded computer, while also
    // making sure we're making forward progress.
    std::string startup_cookie =
        WaitUntilCookieNonEmpty(tab.get(), test_url,
            "STARTUP_COOKIE", TestTimeouts::action_max_timeout_ms());

    // If this fails, the plugin couldn't be loaded in the given amount of
    // time. This may mean the plugin was not found or possibly the system
    // can't load it due to missing symbols, etc.
    ASSERT_STREQ("STARTED", startup_cookie.c_str())
        << "Plugin couldn't be loaded. Make sure the PPAPI test plugin is "
        << "built, in the right place, and doesn't have any missing symbols.";

    std::string escaped_value =
        WaitUntilCookieNonEmpty(tab.get(), test_url,
            "COMPLETION_COOKIE", TestTimeouts::large_test_timeout_ms());
    EXPECT_STREQ("PASS", escaped_value.c_str());
  }
};

TEST_F(PPAPITest, FAILS_Instance) {
  RunTest("Instance");
}

TEST_F(PPAPITest, Graphics2D) {
  RunTest("Graphics2D");
}

TEST_F(PPAPITest, ImageData) {
  RunTest("ImageData");
}

TEST_F(PPAPITest, Buffer) {
  RunTest("Buffer");
}

TEST_F(PPAPITest, URLLoader) {
  RunTestViaHTTP("URLLoader");
}

TEST_F(PPAPITest,PaintAggregator) {
  RunTestViaHTTP("PaintAggregator");
}

TEST_F(PPAPITest, Scrollbar) {
  RunTest("Scrollbar");
}

TEST_F(PPAPITest, URLUtil) {
  RunTest("URLUtil");
}

TEST_F(PPAPITest, CharSet) {
  RunTest("CharSet");
}

TEST_F(PPAPITest, VarDeprecated) {
  RunTest("VarDeprecated");
}

TEST_F(PPAPITest, PostMessage) {
  RunTest("PostMessage");
}

// http://crbug.com/83443
TEST_F(PPAPITest, FAILS_FileIO) {
  RunTestViaHTTP("FileIO");
}

TEST_F(PPAPITest, FileRef) {
  RunTestViaHTTP("FileRef");
}

// http://crbug.com/63239
TEST_F(PPAPITest, DISABLED_DirectoryReader) {
  RunTestViaHTTP("DirectoryReader");
}

#if defined(ENABLE_P2P_APIS)
TEST_F(PPAPITest, Transport) {
  RunTest("Transport");
}
#endif // ENABLE_P2P_APIS
<commit_msg>PPAPITest.Transport is flaky<commit_after>// Copyright (c) 2011 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "base/file_util.h"
#include "base/path_service.h"
#include "base/test/test_timeouts.h"
#include "build/build_config.h"
#include "chrome/common/chrome_switches.h"
#include "chrome/test/automation/tab_proxy.h"
#include "chrome/test/ui/ui_test.h"
#include "net/base/net_util.h"
#include "net/test/test_server.h"
#include "webkit/plugins/plugin_switches.h"

namespace {

// Platform-specific filename relative to the chrome executable.
#if defined(OS_WIN)
const wchar_t library_name[] = L"ppapi_tests.dll";
#elif defined(OS_MACOSX)
const char library_name[] = "ppapi_tests.plugin";
#elif defined(OS_POSIX)
const char library_name[] = "libppapi_tests.so";
#endif

}  // namespace

class PPAPITest : public UITest {
 public:
  PPAPITest() {
    // Append the switch to register the pepper plugin.
    // library name = <out dir>/<test_name>.<library_extension>
    // MIME type = application/x-ppapi-<test_name>
    FilePath plugin_dir;
    PathService::Get(base::DIR_EXE, &plugin_dir);

    FilePath plugin_lib = plugin_dir.Append(library_name);
    EXPECT_TRUE(file_util::PathExists(plugin_lib));
    FilePath::StringType pepper_plugin = plugin_lib.value();
    pepper_plugin.append(FILE_PATH_LITERAL(";application/x-ppapi-tests"));
    launch_arguments_.AppendSwitchNative(switches::kRegisterPepperPlugins,
                                         pepper_plugin);

    // The test sends us the result via a cookie.
    launch_arguments_.AppendSwitch(switches::kEnableFileCookies);

    // Some stuff is hung off of the testing interface which is not enabled
    // by default.
    launch_arguments_.AppendSwitch(switches::kEnablePepperTesting);

    // Give unlimited quota for files to Pepper tests.
    // TODO(dumi): remove this switch once we have a quota management
    // system in place.
    launch_arguments_.AppendSwitch(switches::kUnlimitedQuotaForFiles);

#if defined(ENABLE_P2P_APIS)
    // Enable P2P API.
    launch_arguments_.AppendSwitch(switches::kEnableP2PApi);
#endif // ENABLE_P2P_APIS
  }

  void RunTest(const std::string& test_case) {
    FilePath test_path;
    PathService::Get(base::DIR_SOURCE_ROOT, &test_path);
    test_path = test_path.Append(FILE_PATH_LITERAL("ppapi"));
    test_path = test_path.Append(FILE_PATH_LITERAL("tests"));
    test_path = test_path.Append(FILE_PATH_LITERAL("test_case.html"));

    // Sanity check the file name.
    EXPECT_TRUE(file_util::PathExists(test_path));

    GURL::Replacements replacements;
    std::string query("testcase=");
    query += test_case;
    replacements.SetQuery(query.c_str(), url_parse::Component(0, query.size()));
    GURL test_url = net::FilePathToFileURL(test_path);
    RunTestURL(test_url.ReplaceComponents(replacements));
  }

  void RunTestViaHTTP(const std::string& test_case) {
    net::TestServer test_server(
        net::TestServer::TYPE_HTTP,
        FilePath(FILE_PATH_LITERAL("ppapi/tests")));
    ASSERT_TRUE(test_server.Start());
    RunTestURL(
        test_server.GetURL("files/test_case.html?testcase=" + test_case));
  }

 private:
  void RunTestURL(const GURL& test_url) {
    scoped_refptr<TabProxy> tab(GetActiveTab());
    ASSERT_TRUE(tab.get());
    ASSERT_TRUE(tab->NavigateToURL(test_url));

    // First wait for the "starting" signal. This cookie is set at the start
    // of every test. Waiting for this separately allows us to avoid a single
    // long timeout. Instead, we can have two timeouts which allow startup +
    // test execution time to take a while on a loaded computer, while also
    // making sure we're making forward progress.
    std::string startup_cookie =
        WaitUntilCookieNonEmpty(tab.get(), test_url,
            "STARTUP_COOKIE", TestTimeouts::action_max_timeout_ms());

    // If this fails, the plugin couldn't be loaded in the given amount of
    // time. This may mean the plugin was not found or possibly the system
    // can't load it due to missing symbols, etc.
    ASSERT_STREQ("STARTED", startup_cookie.c_str())
        << "Plugin couldn't be loaded. Make sure the PPAPI test plugin is "
        << "built, in the right place, and doesn't have any missing symbols.";

    std::string escaped_value =
        WaitUntilCookieNonEmpty(tab.get(), test_url,
            "COMPLETION_COOKIE", TestTimeouts::large_test_timeout_ms());
    EXPECT_STREQ("PASS", escaped_value.c_str());
  }
};

TEST_F(PPAPITest, FAILS_Instance) {
  RunTest("Instance");
}

TEST_F(PPAPITest, Graphics2D) {
  RunTest("Graphics2D");
}

TEST_F(PPAPITest, ImageData) {
  RunTest("ImageData");
}

TEST_F(PPAPITest, Buffer) {
  RunTest("Buffer");
}

TEST_F(PPAPITest, URLLoader) {
  RunTestViaHTTP("URLLoader");
}

TEST_F(PPAPITest,PaintAggregator) {
  RunTestViaHTTP("PaintAggregator");
}

TEST_F(PPAPITest, Scrollbar) {
  RunTest("Scrollbar");
}

TEST_F(PPAPITest, URLUtil) {
  RunTest("URLUtil");
}

TEST_F(PPAPITest, CharSet) {
  RunTest("CharSet");
}

TEST_F(PPAPITest, VarDeprecated) {
  RunTest("VarDeprecated");
}

TEST_F(PPAPITest, PostMessage) {
  RunTest("PostMessage");
}

// http://crbug.com/83443
TEST_F(PPAPITest, FAILS_FileIO) {
  RunTestViaHTTP("FileIO");
}

TEST_F(PPAPITest, FileRef) {
  RunTestViaHTTP("FileRef");
}

// http://crbug.com/63239
TEST_F(PPAPITest, DISABLED_DirectoryReader) {
  RunTestViaHTTP("DirectoryReader");
}

#if defined(ENABLE_P2P_APIS)
TEST_F(PPAPITest, FLAKY_Transport) {
  RunTest("Transport");
}
#endif // ENABLE_P2P_APIS
<|endoftext|>


<commit_before>/*
 * pv_example.cpp
 *
 *  Example of a PetaVision application.
 *
 */

#include <stdlib.h>

#include "include/pv_common.h"
#include "columns/HyPerCol.hpp"

#include "layers/Example.hpp"
#include "layers/Retina.hpp"

#include "layers/fileread.h"

int main(int argc, char* argv[])
{
   const char input[] = INPUT_PATH "const_one_64x64.tif";

   PV::HyPerCol * hc = new PV::HyPerCol("column", argc, argv);

   // construct layers
   PV::HyPerLayer * retina  = new PV::Retina("Example Retina", hc, input);
   PV::HyPerLayer * example = new PV::Example("Example Layer", hc);

   // connect the layers
   new PV::HyPerConn("Retina to Example", hc, retina, example, CHANNEL_EXC);

   // finish initialization now that everything is connected
   hc->initFinish();

   // run the simulation for 2 time steps
   hc->run(2);

   hc->writeState();

   // clean up (HyPerCol owns the layers, so don't delete them here)
   delete hc;

   return 0;
}

<commit_msg>Added using namespace PV.<commit_after>/*
 * pv_example.cpp
 *
 *  Example of a PetaVision application.
 *
 */

#include <stdlib.h>

#include "include/pv_common.h"
#include "columns/HyPerCol.hpp"

#include "layers/Example.hpp"
#include "layers/Retina.hpp"

#include "layers/fileread.h"

using namespace PV;

int main(int argc, char* argv[])
{
   const char input[] = INPUT_PATH "const_one_64x64.tif";

   HyPerCol * hc = new HyPerCol("column", argc, argv);

   // construct layers
   HyPerLayer * retina  = new Retina("Example Retina", hc, input);
   HyPerLayer * example = new Example("Example Layer", hc);

   // connect the layers
   new PV::HyPerConn("Retina to Example", hc, retina, example, CHANNEL_EXC);

   // finish initialization now that everything is connected
   hc->initFinish();

   // run the simulation for 2 time steps
   hc->run(2);

   hc->writeState();

   // clean up (HyPerCol owns the layers, so don't delete them here)
   delete hc;

   return 0;
}

<|endoftext|>


<commit_before>/*
-----------------------------------------------------------------------------
This source file is part of OGRE
    (Object-oriented Graphics Rendering Engine)
For the latest info, see http://www.ogre3d.org/

Copyright (c) 2000-2009 Torus Knot Software Ltd

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

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

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

namespace Ogre {

ConfigDialog::ConfigDialog ()
{
}

bool ConfigDialog::display(void)
{
	return true;
}

}
<commit_msg>Symbian port: For now just select the first available render system.<commit_after>/*
-----------------------------------------------------------------------------
This source file is part of OGRE
    (Object-oriented Graphics Rendering Engine)
For the latest info, see http://www.ogre3d.org/

Copyright (c) 2000-2009 Torus Knot Software Ltd

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

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

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

namespace Ogre {

ConfigDialog::ConfigDialog ()
{
}

bool ConfigDialog::display(void)
{
	if(Root::getSingleton().getRenderSystem() != NULL)
	{
		return true;
	}

	// just select the first available render system for now.
	const RenderSystemList* lstRend;
	RenderSystemList::const_iterator pRend;

	lstRend = &Root::getSingleton().getAvailableRenderers();
	pRend = lstRend->begin();

	while (pRend != lstRend->end())
	{
		Root::getSingleton().setRenderSystem((*pRend));

		return true;
	}

	return false;

}

}
<|endoftext|>


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

#include "base/string_util.h"
#include "chrome/app/chrome_dll_resource.h"
#include "chrome/browser/worker_host/worker_service.h"
#include "chrome/common/chrome_switches.h"
#include "chrome/test/automation/browser_proxy.h"
#include "chrome/test/automation/tab_proxy.h"
#include "chrome/test/ui/ui_layout_test.h"

static const char kTestCompleteCookie[] = "status";
static const char kTestCompleteSuccess[] = "OK";

class WorkerTest : public UILayoutTest {
 protected:
  virtual ~WorkerTest() { }

  void RunTest(const std::wstring& test_case) {
    scoped_refptr<TabProxy> tab(GetActiveTab());
    ASSERT_TRUE(tab.get());

    GURL url = GetTestUrl(L"workers", test_case);
    ASSERT_TRUE(tab->NavigateToURL(url));

    std::string value = WaitUntilCookieNonEmpty(tab.get(), url,
        kTestCompleteCookie, kTestIntervalMs, kTestWaitTimeoutMs);
    ASSERT_STREQ(kTestCompleteSuccess, value.c_str());
  }

  void RunIncognitoTest(const std::wstring& test_case) {
    scoped_refptr<BrowserProxy> browser(automation()->GetBrowserWindow(0));
    // Open an Incognito window.
    int window_count;
    ASSERT_TRUE(browser->RunCommand(IDC_NEW_INCOGNITO_WINDOW));
    scoped_refptr<BrowserProxy> incognito(automation()->GetBrowserWindow(1));
    scoped_refptr<TabProxy> tab(incognito->GetTab(0));
    ASSERT_TRUE(automation()->GetBrowserWindowCount(&window_count));
    ASSERT_EQ(2, window_count);

    GURL url = GetTestUrl(L"workers", test_case);
    ASSERT_TRUE(tab->NavigateToURL(url));

    std::string value = WaitUntilCookieNonEmpty(tab.get(), url,
        kTestCompleteCookie, kTestIntervalMs, kTestWaitTimeoutMs);

    // Close the incognito window
    ASSERT_TRUE(incognito->RunCommand(IDC_CLOSE_WINDOW));
    ASSERT_TRUE(automation()->GetBrowserWindowCount(&window_count));
    ASSERT_EQ(1, window_count);

    ASSERT_STREQ(kTestCompleteSuccess, value.c_str());
  }

  bool WaitForProcessCountToBe(int tabs, int workers) {
    // The 1 is for the browser process.
    int number_of_processes = 1 + workers +
        (UITest::in_process_renderer() ? 0 : tabs);
#if defined(OS_LINUX)
    // On Linux, we also have a zygote process and a sandbox host process.
    number_of_processes += 2;
#endif

    int cur_process_count;
    for (int i = 0; i < 10; ++i) {
      cur_process_count = GetBrowserProcessCount();
      if (cur_process_count == number_of_processes)
        return true;

      PlatformThread::Sleep(sleep_timeout_ms() / 10);
    }

    EXPECT_EQ(number_of_processes, cur_process_count);
    return false;
  }
};

TEST_F(WorkerTest, SingleWorker) {
  RunTest(L"single_worker.html");
}

TEST_F(WorkerTest, MultipleWorkers) {
  RunTest(L"multi_worker.html");
}

TEST_F(WorkerTest, SingleSharedWorker) {
  RunTest(L"single_worker.html?shared=true");
}

TEST_F(WorkerTest, MultipleSharedWorkers) {
  RunTest(L"multi_worker.html?shared=true");
}

#if defined(OS_LINUX)
#define IncognitoSharedWorkers FLAKY_IncognitoSharedWorkers
#endif

// Incognito windows should not share workers with non-incognito windows
TEST_F(WorkerTest, IncognitoSharedWorkers) {
  // Load a non-incognito tab and have it create a shared worker
  RunTest(L"incognito_worker.html");
  // Incognito worker should not share with non-incognito
  RunIncognitoTest(L"incognito_worker.html");
}

#if defined(OS_LINUX)
// Crashes on Linux - http://crbug.com/22898
#define WorkerFastLayoutTests DISABLED_WorkerFastLayoutTests
#elif defined (OS_MACOSX)
#define WorkerFastLayoutTests FLAKY_WorkerFastLayoutTests
#endif

TEST_F(WorkerTest, WorkerFastLayoutTests) {
  static const char* kLayoutTestFiles[] = {
    "stress-js-execution.html",
    "use-machine-stack.html",
    "worker-call.html",
#if defined(OS_WIN)
    // This test occasionally fails on valgrind (http://crbug.com/30212).
    "worker-cloneport.html",
#endif
    "worker-close.html",
    "worker-constructor.html",
    "worker-context-gc.html",
    "worker-context-multi-port.html",
    "worker-event-listener.html",
    "worker-gc.html",
    // worker-lifecycle.html relies on layoutTestController.workerThreadCount
    // which is not currently implemented.
    // "worker-lifecycle.html",
    "worker-location.html",
    "worker-messageport.html",
    // Disabled after r27089 (WebKit merge), http://crbug.com/22947
    // "worker-messageport-gc.html",
    "worker-multi-port.html",
    "worker-navigator.html",
    "worker-replace-global-constructor.html",
    "worker-replace-self.html",
    "worker-script-error.html",
    "worker-terminate.html",
    "worker-timeout.html"
  };

  FilePath fast_test_dir;
  fast_test_dir = fast_test_dir.AppendASCII("LayoutTests");
  fast_test_dir = fast_test_dir.AppendASCII("fast");

  FilePath worker_test_dir;
  worker_test_dir = worker_test_dir.AppendASCII("workers");
  InitializeForLayoutTest(fast_test_dir, worker_test_dir, false);

  // Worker tests also rely on common files in js/resources.
  FilePath js_dir = fast_test_dir.AppendASCII("js");
  FilePath resource_dir;
  resource_dir = resource_dir.AppendASCII("resources");
  AddResourceForLayoutTest(js_dir, resource_dir);

  for (size_t i = 0; i < arraysize(kLayoutTestFiles); ++i)
    RunLayoutTest(kLayoutTestFiles[i], false);

  // Navigate away from to a blank page so that any workers are cleaned up. This
  // helps leaks trackers do a better job of reporting.
  scoped_refptr<TabProxy> tab(GetActiveTab());
  GURL about_url(std::string("file://localhost/"));
  ASSERT_EQ(AUTOMATION_MSG_NAVIGATION_SUCCESS, tab->NavigateToURL(about_url));
}

#if defined(OS_WIN) || defined(OS_MACOSX)
// http://crbug.com/27636 - incorrect URL_MISMATCH exceptions sometimes get
// generated on the windows try bots.
// http://crbug.com/28445 - flakiness on mac
#define SharedWorkerFastLayoutTests FLAKY_SharedWorkerFastLayoutTests
#endif

#if defined(OS_LINUX) && defined(TOOLKIT_VIEWS)
// These tests are flaky on linux/views builds.
// See http://crbug.com/28808.
#define MessagePorts FLAKY_MessagePorts
#define SharedWorkerFastLayoutTests FLAKY_SharedWorkerFastLayoutTests
#endif

TEST_F(WorkerTest, SharedWorkerFastLayoutTests) {
  static const char* kLayoutTestFiles[] = {
    "shared-worker-constructor.html",
    "shared-worker-context-gc.html",
    "shared-worker-event-listener.html",
    "shared-worker-exception.html",
    "shared-worker-gc.html",
    // Lifecycle tests rely on layoutTestController.workerThreadCount which is
    // not currently implemented.
    //"shared-worker-frame-lifecycle.html",
    //"shared-worker-lifecycle.html",
    "shared-worker-load-error.html",
    "shared-worker-location.html",
    "shared-worker-name.html",
    "shared-worker-navigator.html",
    "shared-worker-replace-global-constructor.html",
    "shared-worker-replace-self.html",
    "shared-worker-script-error.html",
    "shared-worker-shared.html",
    "shared-worker-simple.html",
  };

  FilePath fast_test_dir;
  fast_test_dir = fast_test_dir.AppendASCII("LayoutTests");
  fast_test_dir = fast_test_dir.AppendASCII("fast");

  FilePath worker_test_dir;
  worker_test_dir = worker_test_dir.AppendASCII("workers");
  InitializeForLayoutTest(fast_test_dir, worker_test_dir, false);

  // Worker tests also rely on common files in js/resources.
  FilePath js_dir = fast_test_dir.AppendASCII("js");
  FilePath resource_dir;
  resource_dir = resource_dir.AppendASCII("resources");
  AddResourceForLayoutTest(js_dir, resource_dir);

  for (size_t i = 0; i < arraysize(kLayoutTestFiles); ++i) {
    RunLayoutTest(kLayoutTestFiles[i], false);
    // Shared workers will error out if we ever have more than one tab open.
    int window_count = 0;
    ASSERT_TRUE(automation()->GetBrowserWindowCount(&window_count));
    ASSERT_EQ(1, window_count);
    EXPECT_EQ(1, GetTabCount());
  }
}

TEST_F(WorkerTest, WorkerHttpLayoutTests) {
  static const char* kLayoutTestFiles[] = {
    "shared-worker-importScripts.html",
    "shared-worker-redirect.html",
    // flakey? BUG 16934 "text-encoding.html",
#if defined(OS_WIN)
    // Fails on the mac (and linux?):
    // http://code.google.com/p/chromium/issues/detail?id=22599
    "worker-importScripts.html",
#endif
    "worker-redirect.html",
  };

  FilePath http_test_dir;
  http_test_dir = http_test_dir.AppendASCII("LayoutTests");
  http_test_dir = http_test_dir.AppendASCII("http");
  http_test_dir = http_test_dir.AppendASCII("tests");

  FilePath worker_test_dir;
  worker_test_dir = worker_test_dir.AppendASCII("workers");
  InitializeForLayoutTest(http_test_dir, worker_test_dir, true);

  StartHttpServer(new_http_root_dir_);
  for (size_t i = 0; i < arraysize(kLayoutTestFiles); ++i)
    RunLayoutTest(kLayoutTestFiles[i], true);
  StopHttpServer();
}

TEST_F(WorkerTest, WorkerXhrHttpLayoutTests) {
  static const char* kLayoutTestFiles[] = {
    "abort-exception-assert.html",
#if defined(OS_WIN)
    // Fails on the mac (and linux?):
    // http://code.google.com/p/chromium/issues/detail?id=22599
    "close.html",
#endif
    // These tests (and the shared-worker versions below) are disabled due to
    // limitations in lighttpd (doesn't handle all of the HTTP methods).
    //"methods-async.html",
    //"methods.html",

    "shared-worker-close.html",
    // Disabled due to limitations in lighttpd (does not handle methods other
    // than GET/PUT/POST).
    //"shared-worker-methods-async.html",
    //"shared-worker-methods.html",
    "shared-worker-xhr-file-not-found.html",

    "xmlhttprequest-file-not-found.html"
  };

  FilePath http_test_dir;
  http_test_dir = http_test_dir.AppendASCII("LayoutTests");
  http_test_dir = http_test_dir.AppendASCII("http");
  http_test_dir = http_test_dir.AppendASCII("tests");

  FilePath worker_test_dir;
  worker_test_dir = worker_test_dir.AppendASCII("xmlhttprequest");
  worker_test_dir = worker_test_dir.AppendASCII("workers");
  InitializeForLayoutTest(http_test_dir, worker_test_dir, true);

  StartHttpServer(new_http_root_dir_);
  for (size_t i = 0; i < arraysize(kLayoutTestFiles); ++i)
    RunLayoutTest(kLayoutTestFiles[i], true);
  StopHttpServer();
}

TEST_F(WorkerTest, MessagePorts) {
  static const char* kLayoutTestFiles[] = {
    "message-channel-gc.html",
    "message-channel-gc-2.html",
    "message-channel-gc-3.html",
    "message-channel-gc-4.html",
    "message-port.html",
    "message-port-clone.html",
    "message-port-constructor-for-deleted-document.html",
    "message-port-deleted-document.html",
    "message-port-deleted-frame.html",
    "message-port-inactive-document.html",
    "message-port-multi.html",
    "message-port-no-wrapper.html",
    // Only works with run-webkit-tests --leaks.
    //"message-channel-listener-circular-ownership.html",
  };

  FilePath fast_test_dir;
  fast_test_dir = fast_test_dir.AppendASCII("LayoutTests");
  fast_test_dir = fast_test_dir.AppendASCII("fast");

  FilePath worker_test_dir;
  worker_test_dir = worker_test_dir.AppendASCII("events");
  InitializeForLayoutTest(fast_test_dir, worker_test_dir, false);

  // MessagePort tests also rely on common files in js/resources.
  FilePath js_dir = fast_test_dir.AppendASCII("js");
  FilePath resource_dir;
  resource_dir = resource_dir.AppendASCII("resources");
  AddResourceForLayoutTest(js_dir, resource_dir);

  for (size_t i = 0; i < arraysize(kLayoutTestFiles); ++i)
    RunLayoutTest(kLayoutTestFiles[i], false);
}

TEST_F(WorkerTest, LimitPerPage) {
  int max_workers_per_tab = WorkerService::kMaxWorkersPerTabWhenSeparate;
  GURL url = GetTestUrl(L"workers", L"many_workers.html");
  url = GURL(url.spec() + StringPrintf("?count=%d", max_workers_per_tab + 1));

  scoped_refptr<TabProxy> tab(GetActiveTab());
  ASSERT_TRUE(tab.get());
  ASSERT_TRUE(tab->NavigateToURL(url));

  ASSERT_TRUE(WaitForProcessCountToBe(1, max_workers_per_tab));
}

#if defined(OS_LINUX) || defined(OS_MACOSX)
// Doesn't crash, but on Mac it sometimes fails for a few runs in a row,
// http://crbug.com/28445
#define LimitTotal FLAKY_LimitTotal
#endif

TEST_F(WorkerTest, LimitTotal) {
  int max_workers_per_tab = WorkerService::kMaxWorkersPerTabWhenSeparate;
  int total_workers = WorkerService::kMaxWorkersWhenSeparate;

  int tab_count = (total_workers / max_workers_per_tab) + 1;
  GURL url = GetTestUrl(L"workers", L"many_workers.html");
  url = GURL(url.spec() + StringPrintf("?count=%d", max_workers_per_tab));

  scoped_refptr<TabProxy> tab(GetActiveTab());
  ASSERT_TRUE(tab.get());
  ASSERT_TRUE(tab->NavigateToURL(url));
  scoped_refptr<BrowserProxy> window(automation()->GetBrowserWindow(0));
  for (int i = 1; i < tab_count; ++i)
    window->AppendTab(url);

  // Check that we didn't create more than the max number of workers.
  ASSERT_TRUE(WaitForProcessCountToBe(tab_count, total_workers));

  // Now close a page and check that the queued workers were started.
  tab->NavigateToURL(GetTestUrl(L"google", L"google.html"));

  ASSERT_TRUE(WaitForProcessCountToBe(tab_count, total_workers));
}
<commit_msg>Comments out WorkerTest.FLAKY_LimitTotal on Linux. Since Build 3442, this test has been causing an error "chrome: Fatal IO error 11 (Resource temporarily unavailable) on X server :9.0" on the "Chromium Linux (x64)" bot, and making the bot hang-up. To investigate this hang-up, this change temporarily comments out this test on Linux.<commit_after>// Copyright (c) 2009 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "base/string_util.h"
#include "chrome/app/chrome_dll_resource.h"
#include "chrome/browser/worker_host/worker_service.h"
#include "chrome/common/chrome_switches.h"
#include "chrome/test/automation/browser_proxy.h"
#include "chrome/test/automation/tab_proxy.h"
#include "chrome/test/ui/ui_layout_test.h"

static const char kTestCompleteCookie[] = "status";
static const char kTestCompleteSuccess[] = "OK";

class WorkerTest : public UILayoutTest {
 protected:
  virtual ~WorkerTest() { }

  void RunTest(const std::wstring& test_case) {
    scoped_refptr<TabProxy> tab(GetActiveTab());
    ASSERT_TRUE(tab.get());

    GURL url = GetTestUrl(L"workers", test_case);
    ASSERT_TRUE(tab->NavigateToURL(url));

    std::string value = WaitUntilCookieNonEmpty(tab.get(), url,
        kTestCompleteCookie, kTestIntervalMs, kTestWaitTimeoutMs);
    ASSERT_STREQ(kTestCompleteSuccess, value.c_str());
  }

  void RunIncognitoTest(const std::wstring& test_case) {
    scoped_refptr<BrowserProxy> browser(automation()->GetBrowserWindow(0));
    // Open an Incognito window.
    int window_count;
    ASSERT_TRUE(browser->RunCommand(IDC_NEW_INCOGNITO_WINDOW));
    scoped_refptr<BrowserProxy> incognito(automation()->GetBrowserWindow(1));
    scoped_refptr<TabProxy> tab(incognito->GetTab(0));
    ASSERT_TRUE(automation()->GetBrowserWindowCount(&window_count));
    ASSERT_EQ(2, window_count);

    GURL url = GetTestUrl(L"workers", test_case);
    ASSERT_TRUE(tab->NavigateToURL(url));

    std::string value = WaitUntilCookieNonEmpty(tab.get(), url,
        kTestCompleteCookie, kTestIntervalMs, kTestWaitTimeoutMs);

    // Close the incognito window
    ASSERT_TRUE(incognito->RunCommand(IDC_CLOSE_WINDOW));
    ASSERT_TRUE(automation()->GetBrowserWindowCount(&window_count));
    ASSERT_EQ(1, window_count);

    ASSERT_STREQ(kTestCompleteSuccess, value.c_str());
  }

  bool WaitForProcessCountToBe(int tabs, int workers) {
    // The 1 is for the browser process.
    int number_of_processes = 1 + workers +
        (UITest::in_process_renderer() ? 0 : tabs);
#if defined(OS_LINUX)
    // On Linux, we also have a zygote process and a sandbox host process.
    number_of_processes += 2;
#endif

    int cur_process_count;
    for (int i = 0; i < 10; ++i) {
      cur_process_count = GetBrowserProcessCount();
      if (cur_process_count == number_of_processes)
        return true;

      PlatformThread::Sleep(sleep_timeout_ms() / 10);
    }

    EXPECT_EQ(number_of_processes, cur_process_count);
    return false;
  }
};

TEST_F(WorkerTest, SingleWorker) {
  RunTest(L"single_worker.html");
}

TEST_F(WorkerTest, MultipleWorkers) {
  RunTest(L"multi_worker.html");
}

TEST_F(WorkerTest, SingleSharedWorker) {
  RunTest(L"single_worker.html?shared=true");
}

TEST_F(WorkerTest, MultipleSharedWorkers) {
  RunTest(L"multi_worker.html?shared=true");
}

#if defined(OS_LINUX)
#define IncognitoSharedWorkers FLAKY_IncognitoSharedWorkers
#endif

// Incognito windows should not share workers with non-incognito windows
TEST_F(WorkerTest, IncognitoSharedWorkers) {
  // Load a non-incognito tab and have it create a shared worker
  RunTest(L"incognito_worker.html");
  // Incognito worker should not share with non-incognito
  RunIncognitoTest(L"incognito_worker.html");
}

#if defined(OS_LINUX)
// Crashes on Linux - http://crbug.com/22898
#define WorkerFastLayoutTests DISABLED_WorkerFastLayoutTests
#elif defined (OS_MACOSX)
#define WorkerFastLayoutTests FLAKY_WorkerFastLayoutTests
#endif

TEST_F(WorkerTest, WorkerFastLayoutTests) {
  static const char* kLayoutTestFiles[] = {
    "stress-js-execution.html",
    "use-machine-stack.html",
    "worker-call.html",
#if defined(OS_WIN)
    // This test occasionally fails on valgrind (http://crbug.com/30212).
    "worker-cloneport.html",
#endif
    "worker-close.html",
    "worker-constructor.html",
    "worker-context-gc.html",
    "worker-context-multi-port.html",
    "worker-event-listener.html",
    "worker-gc.html",
    // worker-lifecycle.html relies on layoutTestController.workerThreadCount
    // which is not currently implemented.
    // "worker-lifecycle.html",
    "worker-location.html",
    "worker-messageport.html",
    // Disabled after r27089 (WebKit merge), http://crbug.com/22947
    // "worker-messageport-gc.html",
    "worker-multi-port.html",
    "worker-navigator.html",
    "worker-replace-global-constructor.html",
    "worker-replace-self.html",
    "worker-script-error.html",
    "worker-terminate.html",
    "worker-timeout.html"
  };

  FilePath fast_test_dir;
  fast_test_dir = fast_test_dir.AppendASCII("LayoutTests");
  fast_test_dir = fast_test_dir.AppendASCII("fast");

  FilePath worker_test_dir;
  worker_test_dir = worker_test_dir.AppendASCII("workers");
  InitializeForLayoutTest(fast_test_dir, worker_test_dir, false);

  // Worker tests also rely on common files in js/resources.
  FilePath js_dir = fast_test_dir.AppendASCII("js");
  FilePath resource_dir;
  resource_dir = resource_dir.AppendASCII("resources");
  AddResourceForLayoutTest(js_dir, resource_dir);

  for (size_t i = 0; i < arraysize(kLayoutTestFiles); ++i)
    RunLayoutTest(kLayoutTestFiles[i], false);

  // Navigate away from to a blank page so that any workers are cleaned up. This
  // helps leaks trackers do a better job of reporting.
  scoped_refptr<TabProxy> tab(GetActiveTab());
  GURL about_url(std::string("file://localhost/"));
  ASSERT_EQ(AUTOMATION_MSG_NAVIGATION_SUCCESS, tab->NavigateToURL(about_url));
}

#if defined(OS_WIN) || defined(OS_MACOSX)
// http://crbug.com/27636 - incorrect URL_MISMATCH exceptions sometimes get
// generated on the windows try bots.
// http://crbug.com/28445 - flakiness on mac
#define SharedWorkerFastLayoutTests FLAKY_SharedWorkerFastLayoutTests
#endif

#if defined(OS_LINUX) && defined(TOOLKIT_VIEWS)
// These tests are flaky on linux/views builds.
// See http://crbug.com/28808.
#define MessagePorts FLAKY_MessagePorts
#define SharedWorkerFastLayoutTests FLAKY_SharedWorkerFastLayoutTests
#endif

TEST_F(WorkerTest, SharedWorkerFastLayoutTests) {
  static const char* kLayoutTestFiles[] = {
    "shared-worker-constructor.html",
    "shared-worker-context-gc.html",
    "shared-worker-event-listener.html",
    "shared-worker-exception.html",
    "shared-worker-gc.html",
    // Lifecycle tests rely on layoutTestController.workerThreadCount which is
    // not currently implemented.
    //"shared-worker-frame-lifecycle.html",
    //"shared-worker-lifecycle.html",
    "shared-worker-load-error.html",
    "shared-worker-location.html",
    "shared-worker-name.html",
    "shared-worker-navigator.html",
    "shared-worker-replace-global-constructor.html",
    "shared-worker-replace-self.html",
    "shared-worker-script-error.html",
    "shared-worker-shared.html",
    "shared-worker-simple.html",
  };

  FilePath fast_test_dir;
  fast_test_dir = fast_test_dir.AppendASCII("LayoutTests");
  fast_test_dir = fast_test_dir.AppendASCII("fast");

  FilePath worker_test_dir;
  worker_test_dir = worker_test_dir.AppendASCII("workers");
  InitializeForLayoutTest(fast_test_dir, worker_test_dir, false);

  // Worker tests also rely on common files in js/resources.
  FilePath js_dir = fast_test_dir.AppendASCII("js");
  FilePath resource_dir;
  resource_dir = resource_dir.AppendASCII("resources");
  AddResourceForLayoutTest(js_dir, resource_dir);

  for (size_t i = 0; i < arraysize(kLayoutTestFiles); ++i) {
    RunLayoutTest(kLayoutTestFiles[i], false);
    // Shared workers will error out if we ever have more than one tab open.
    int window_count = 0;
    ASSERT_TRUE(automation()->GetBrowserWindowCount(&window_count));
    ASSERT_EQ(1, window_count);
    EXPECT_EQ(1, GetTabCount());
  }
}

TEST_F(WorkerTest, WorkerHttpLayoutTests) {
  static const char* kLayoutTestFiles[] = {
    "shared-worker-importScripts.html",
    "shared-worker-redirect.html",
    // flakey? BUG 16934 "text-encoding.html",
#if defined(OS_WIN)
    // Fails on the mac (and linux?):
    // http://code.google.com/p/chromium/issues/detail?id=22599
    "worker-importScripts.html",
#endif
    "worker-redirect.html",
  };

  FilePath http_test_dir;
  http_test_dir = http_test_dir.AppendASCII("LayoutTests");
  http_test_dir = http_test_dir.AppendASCII("http");
  http_test_dir = http_test_dir.AppendASCII("tests");

  FilePath worker_test_dir;
  worker_test_dir = worker_test_dir.AppendASCII("workers");
  InitializeForLayoutTest(http_test_dir, worker_test_dir, true);

  StartHttpServer(new_http_root_dir_);
  for (size_t i = 0; i < arraysize(kLayoutTestFiles); ++i)
    RunLayoutTest(kLayoutTestFiles[i], true);
  StopHttpServer();
}

TEST_F(WorkerTest, WorkerXhrHttpLayoutTests) {
  static const char* kLayoutTestFiles[] = {
    "abort-exception-assert.html",
#if defined(OS_WIN)
    // Fails on the mac (and linux?):
    // http://code.google.com/p/chromium/issues/detail?id=22599
    "close.html",
#endif
    // These tests (and the shared-worker versions below) are disabled due to
    // limitations in lighttpd (doesn't handle all of the HTTP methods).
    //"methods-async.html",
    //"methods.html",

    "shared-worker-close.html",
    // Disabled due to limitations in lighttpd (does not handle methods other
    // than GET/PUT/POST).
    //"shared-worker-methods-async.html",
    //"shared-worker-methods.html",
    "shared-worker-xhr-file-not-found.html",

    "xmlhttprequest-file-not-found.html"
  };

  FilePath http_test_dir;
  http_test_dir = http_test_dir.AppendASCII("LayoutTests");
  http_test_dir = http_test_dir.AppendASCII("http");
  http_test_dir = http_test_dir.AppendASCII("tests");

  FilePath worker_test_dir;
  worker_test_dir = worker_test_dir.AppendASCII("xmlhttprequest");
  worker_test_dir = worker_test_dir.AppendASCII("workers");
  InitializeForLayoutTest(http_test_dir, worker_test_dir, true);

  StartHttpServer(new_http_root_dir_);
  for (size_t i = 0; i < arraysize(kLayoutTestFiles); ++i)
    RunLayoutTest(kLayoutTestFiles[i], true);
  StopHttpServer();
}

TEST_F(WorkerTest, MessagePorts) {
  static const char* kLayoutTestFiles[] = {
    "message-channel-gc.html",
    "message-channel-gc-2.html",
    "message-channel-gc-3.html",
    "message-channel-gc-4.html",
    "message-port.html",
    "message-port-clone.html",
    "message-port-constructor-for-deleted-document.html",
    "message-port-deleted-document.html",
    "message-port-deleted-frame.html",
    "message-port-inactive-document.html",
    "message-port-multi.html",
    "message-port-no-wrapper.html",
    // Only works with run-webkit-tests --leaks.
    //"message-channel-listener-circular-ownership.html",
  };

  FilePath fast_test_dir;
  fast_test_dir = fast_test_dir.AppendASCII("LayoutTests");
  fast_test_dir = fast_test_dir.AppendASCII("fast");

  FilePath worker_test_dir;
  worker_test_dir = worker_test_dir.AppendASCII("events");
  InitializeForLayoutTest(fast_test_dir, worker_test_dir, false);

  // MessagePort tests also rely on common files in js/resources.
  FilePath js_dir = fast_test_dir.AppendASCII("js");
  FilePath resource_dir;
  resource_dir = resource_dir.AppendASCII("resources");
  AddResourceForLayoutTest(js_dir, resource_dir);

  for (size_t i = 0; i < arraysize(kLayoutTestFiles); ++i)
    RunLayoutTest(kLayoutTestFiles[i], false);
}

TEST_F(WorkerTest, LimitPerPage) {
  int max_workers_per_tab = WorkerService::kMaxWorkersPerTabWhenSeparate;
  GURL url = GetTestUrl(L"workers", L"many_workers.html");
  url = GURL(url.spec() + StringPrintf("?count=%d", max_workers_per_tab + 1));

  scoped_refptr<TabProxy> tab(GetActiveTab());
  ASSERT_TRUE(tab.get());
  ASSERT_TRUE(tab->NavigateToURL(url));

  ASSERT_TRUE(WaitForProcessCountToBe(1, max_workers_per_tab));
}

#if defined(OS_LINUX) || defined(OS_MACOSX)
// Doesn't crash, but on Mac it sometimes fails for a few runs in a row,
// http://crbug.com/28445
#define LimitTotal FLAKY_LimitTotal
#endif

TEST_F(WorkerTest, LimitTotal) {
#if !defined(OS_LINUX)
  int max_workers_per_tab = WorkerService::kMaxWorkersPerTabWhenSeparate;
  int total_workers = WorkerService::kMaxWorkersWhenSeparate;

  int tab_count = (total_workers / max_workers_per_tab) + 1;
  GURL url = GetTestUrl(L"workers", L"many_workers.html");
  url = GURL(url.spec() + StringPrintf("?count=%d", max_workers_per_tab));

  scoped_refptr<TabProxy> tab(GetActiveTab());
  ASSERT_TRUE(tab.get());
  ASSERT_TRUE(tab->NavigateToURL(url));
  scoped_refptr<BrowserProxy> window(automation()->GetBrowserWindow(0));
  for (int i = 1; i < tab_count; ++i)
    window->AppendTab(url);

  // Check that we didn't create more than the max number of workers.
  ASSERT_TRUE(WaitForProcessCountToBe(tab_count, total_workers));

  // Now close a page and check that the queued workers were started.
  tab->NavigateToURL(GetTestUrl(L"google", L"google.html"));

  ASSERT_TRUE(WaitForProcessCountToBe(tab_count, total_workers));
#endif
}
<|endoftext|>