<commit_before>///////////////////////////////////////////////////////////////////////////////
// This source file is part of Hect.
//
// Copyright (c) 2015 Colin Hill
//
// 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 "DataValue.h"

#define YAML_DECLARE_STATIC
#include <yaml.h>

#include "Hect/IO/ReadStream.h"
#include "Hect/IO/WriteStream.h"

using namespace hect;

const DataValue DataValue::_null;
const DataValue::Array DataValue::_emptyArray;

DataValue::DataValue() :
    _type(DataValueType::Null)
{
}

DataValue::DataValue(DataValueType type) :
    _type(type)
{
    switch (type)
    {
    case DataValueType::Bool:
        _any = false;
        break;
    case DataValueType::Number:
        _any = 0.0;
        break;
    case DataValueType::String:
        _any = std::string();
        break;
    case DataValueType::Array:
        _any = DataValue::Array();
        break;
    case DataValueType::Object:
        _any = DataValue::Object();
        break;
    default:
        break;
    }
}

DataValue::DataValue(bool value) :
    _type(DataValueType::Bool),
    _any(value)
{
}

DataValue::DataValue(int value) :
    _type(DataValueType::Number),
    _any((double)value)
{
}

DataValue::DataValue(unsigned value) :
    _type(DataValueType::Number),
    _any((double)value)
{
}

DataValue::DataValue(double value) :
    _type(DataValueType::Number),
    _any(value)
{
}

DataValue::DataValue(const Vector2& value) :
    _type(DataValueType::Array),
    _any(DataValue::Array())
{
    DataValue::Array& elements = _any.as<DataValue::Array>();
    elements.push_back(value.x);
    elements.push_back(value.y);
}

DataValue::DataValue(const Vector3& value) :
    _type(DataValueType::Array),
    _any(DataValue::Array())
{
    DataValue::Array& elements = _any.as<DataValue::Array>();
    elements.push_back(value.x);
    elements.push_back(value.y);
    elements.push_back(value.z);
}

DataValue::DataValue(const Vector4& value) :
    _type(DataValueType::Array),
    _any(DataValue::Array())
{
    DataValue::Array& elements = _any.as<DataValue::Array>();
    elements.push_back(value.x);
    elements.push_back(value.y);
    elements.push_back(value.z);
    elements.push_back(value.w);
}

DataValue::DataValue(const Matrix4& value) :
    _type(DataValueType::Array),
    _any(DataValue::Array())
{
    DataValue::Array& elements = _any.as<DataValue::Array>();
    for (unsigned i = 0; i < 16; ++i)
    {
        elements.push_back(value[i]);
    }
}

DataValue::DataValue(const Quaternion& value) :
    _type(DataValueType::Array),
    _any(DataValue::Array())
{
    DataValue::Array& elements = _any.as<DataValue::Array>();
    elements.push_back(value.x);
    elements.push_back(value.y);
    elements.push_back(value.z);
    elements.push_back(value.w);
}

DataValue::DataValue(const char* value) :
    _type(DataValueType::String),
    _any(std::string(value))
{
}

DataValue::DataValue(const std::string& value) :
    _type(DataValueType::String),
    _any(value)
{
}

DataValue::DataValue(const DataValue& dataValue) :
    _type(dataValue._type),
    _any(dataValue._any)
{
}

DataValue::DataValue(DataValue&& dataValue) :
    _type(dataValue._type),
    _any(std::move(dataValue._any))
{
    dataValue._type = DataValueType::Null;
}

DataValueType DataValue::type() const
{
    return _type;
}

const DataValue& DataValue::orDefault(const DataValue& dataValue) const
{
    if (isNull())
    {
        return dataValue;
    }
    else
    {
        return *this;
    }
}

bool DataValue::isNull() const
{
    return _type == DataValueType::Null;
}

bool DataValue::isBool() const
{
    return _type == DataValueType::Bool;
}

bool DataValue::isNumber() const
{
    return _type == DataValueType::Number;
}

bool DataValue::isString() const
{
    return _type == DataValueType::String;
}

bool DataValue::isArray() const
{
    return _type == DataValueType::Array;
}

bool DataValue::isObject() const
{
    return _type == DataValueType::Object;
}

bool DataValue::asBool() const
{
    if (isBool())
    {
        return _any.as<bool>();
    }
    else
    {
        return false;
    }
}

int DataValue::asInt() const
{
    if (isNumber())
    {
        return (int)_any.as<double>();
    }
    else
    {
        return 0;
    }
}

unsigned DataValue::asUnsigned() const
{
    if (isNumber())
    {
        return (unsigned)_any.as<double>();
    }
    else
    {
        return 0;
    }
}

double DataValue::asDouble() const
{
    if (isNumber())
    {
        return _any.as<double>();
    }
    else
    {
        return 0.0;
    }
}

Vector2 DataValue::asVector2() const
{
    Vector2 result;

    size_t i = 0;
    for (const DataValue& component : *this)
    {
        if (i < 2)
        {
            result[i++] = component.asDouble();
        }
        else
        {
            break;
        }
    }

    return result;
}

Vector3 DataValue::asVector3() const
{
    Vector3 result;

    size_t i = 0;
    for (const DataValue& component : *this)
    {
        if (i < 3)
        {
            result[i++] = component.asDouble();
        }
        else
        {
            break;
        }
    }

    return result;
}

Vector4 DataValue::asVector4() const
{
    Vector4 result;

    size_t i = 0;
    for (const DataValue& component : *this)
    {
        if (i < 4)
        {
            result[i++] = component.asDouble();
        }
        else
        {
            break;
        }
    }

    return result;
}

Matrix4 DataValue::asMatrix4() const
{
    Matrix4 result;

    size_t i = 0;
    for (const DataValue& component : *this)
    {
        if (i < 16)
        {
            result[i++] = component.asDouble();
        }
        else
        {
            break;
        }
    }

    return result;
}

Quaternion DataValue::asQuaternion() const
{
    Quaternion result;

    size_t i = 0;
    for (const DataValue& component : *this)
    {
        if (i < 4)
        {
            result[i++] = component.asDouble();
        }
        else
        {
            break;
        }
    }

    return result;
}

const std::string& DataValue::asString() const
{
    static std::string empty;

    if (isString())
    {
        return _any.as<std::string>();
    }
    else
    {
        return empty;
    }
}

size_t DataValue::size() const
{
    if (isArray())
    {
        return _any.as<DataValue::Array>().size();
    }
    else if (isObject())
    {
        return _any.as<DataValue::Object>().size();
    }

    return 0;
}

std::vector<std::string> DataValue::memberNames() const
{
    if (isObject())
    {
        std::vector<std::string> result;
        for (auto& pair : _any.as<DataValue::Object>())
        {
            result.push_back(pair.first);
        }
        return result;
    }
    else
    {
        return std::vector<std::string>();
    }
}

void DataValue::addMember(const std::string& name, const DataValue& dataValue)
{
    if (isObject())
    {
        _any.as<DataValue::Object>()[name] = dataValue;
    }
    else
    {
        throw InvalidOperation("The data value is not an object");
    }
}

void DataValue::addElement(const DataValue& dataValue)
{
    if (isArray())
    {
        _any.as<DataValue::Array>().push_back(dataValue);
    }
    else
    {
        throw InvalidOperation("The data value is not an array");
    }
}

const DataValue& DataValue::operator[](size_t index) const
{
    if (isArray())
    {
        const Array& array = _any.as<DataValue::Array>();
        if (index < array.size())
        {
            return array[index];
        }
        else
        {
            return _null;
        }
    }
    else
    {
        return _null;
    }
}

const DataValue& DataValue::operator[](const std::string& name) const
{
    if (isObject())
    {
        const DataValue::Object& members = _any.as<DataValue::Object>();
        auto it = members.find(name);
        if (it == members.end())
        {
            return _null;
        }
        return (*it).second;
    }
    else
    {
        return _null;
    }
}

DataValue& DataValue::operator=(const DataValue& dataValue)
{
    _type = dataValue._type;
    _any = dataValue._any;
    return *this;
}

DataValue& DataValue::operator=(DataValue&& dataValue)
{
    _type = dataValue._type;
    _any = std::move(dataValue._any);
    return *this;
}

DataValue::Array::const_iterator DataValue::begin() const
{
    if (isArray())
    {
        return _any.as<DataValue::Array>().begin();
    }
    else
    {
        return _emptyArray.begin();
    }
}

DataValue::Array::const_iterator DataValue::end() const
{
    if (isArray())
    {
        return _any.as<DataValue::Array>().end();
    }
    else
    {
        return _emptyArray.end();
    }
}

namespace hect
{

// Converts a YAML node to a DataValue
DataValue fromYaml(yaml_document_t* document, yaml_node_t* node)
{
    assert(document);
    assert(node);

    switch (node->type)
    {
    case YAML_SCALAR_NODE:
    {
        const char* value = reinterpret_cast<const char*>(node->data.scalar.value);
        std::string string(value);

        // Check if it is a bool
        if (string == "true" || string == "false")
        {
            bool boolValue = string == "true";
            return DataValue(boolValue);
        }
        else if (value)
        {
            // Attempt to parse a double from the value
            char* end = nullptr;
            double numberValue = std::strtod(value, &end);
            if (end && *end == '\0')
            {
                // It is a valid number
                return DataValue(numberValue);
            }
        }

        // Otherwise it is just a string
        return DataValue(string);
    }
    case YAML_SEQUENCE_NODE:
    {
        DataValue dataValue(DataValueType::Array);

        // For each item in the sequence
        for (yaml_node_item_t* item = node->data.sequence.items.start;
                item < node->data.sequence.items.top; item++)
        {
            // Convert the item to a DataValue
            yaml_node_t* itemNode = yaml_document_get_node(document, *item);
            DataValue element = fromYaml(document, itemNode);

            // Add the element
            dataValue.addElement(element);
        }

        return dataValue;
    }
    case YAML_MAPPING_NODE:
    {
        DataValue dataValue(DataValueType::Object);

        // For each pair in the mapping
        for (yaml_node_pair_t* pair = node->data.mapping.pairs.start;
                pair < node->data.mapping.pairs.top; pair++)
        {
            // Get the name from the pair
            yaml_node_t* keyNode = yaml_document_get_node(document, pair->key);
            const char* name = reinterpret_cast<const char*>(keyNode->data.scalar.value);

            // Convert the value node to a DataValue
            yaml_node_t* valueNode = yaml_document_get_node(document, pair->value);
            DataValue value = fromYaml(document, valueNode);

            // Add the member
            dataValue.addMember(name, value);
        }

        return dataValue;
    }
    default:
        return DataValue();
    }
}

}

void DataValue::decodeFromYaml(const std::string& yaml)
{
    // Initialize the parser
    yaml_parser_t parser;
    yaml_parser_initialize(&parser);
    yaml_parser_set_input_string(&parser, reinterpret_cast<const unsigned char*>(yaml.c_str()), yaml.size());

    // Attempt to parse the document
    yaml_document_t document;
    std::string errorMessage;
    if (!yaml_parser_load(&parser, &document))
    {
        // Remember the error message
        errorMessage = format("Invalid YAML: %s on line %i column %i", parser.problem, parser.problem_mark.line, parser.problem_mark.column);
    }

    if (errorMessage.empty())
    {
        yaml_node_t* node = yaml_document_get_root_node(&document);
        if (node)
        {
            // Convert all nodes recursively
            *this = fromYaml(&document, node);
        }
    }

    // Clean up document and parser
    yaml_document_delete(&document);
    yaml_parser_delete(&parser);

    // Throw the error if there was one
    if (!errorMessage.empty())
    {
        throw DecodeError(errorMessage);
    }
}

void DataValue::decodeFromYaml(ReadStream& stream)
{
    decodeFromYaml(stream.readAllToString());
}
<commit_msg>Revert "Another shot of avoiding the Valgrind false positive"<commit_after>///////////////////////////////////////////////////////////////////////////////
// This source file is part of Hect.
//
// Copyright (c) 2015 Colin Hill
//
// 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 "DataValue.h"

#define YAML_DECLARE_STATIC
#include <yaml.h>

#include <sstream>

#include "Hect/IO/ReadStream.h"
#include "Hect/IO/WriteStream.h"

using namespace hect;

const DataValue DataValue::_null;
const DataValue::Array DataValue::_emptyArray;

DataValue::DataValue() :
    _type(DataValueType::Null)
{
}

DataValue::DataValue(DataValueType type) :
    _type(type)
{
    switch (type)
    {
    case DataValueType::Bool:
        _any = false;
        break;
    case DataValueType::Number:
        _any = 0.0;
        break;
    case DataValueType::String:
        _any = std::string();
        break;
    case DataValueType::Array:
        _any = DataValue::Array();
        break;
    case DataValueType::Object:
        _any = DataValue::Object();
        break;
    default:
        break;
    }
}

DataValue::DataValue(bool value) :
    _type(DataValueType::Bool),
    _any(value)
{
}

DataValue::DataValue(int value) :
    _type(DataValueType::Number),
    _any((double)value)
{
}

DataValue::DataValue(unsigned value) :
    _type(DataValueType::Number),
    _any((double)value)
{
}

DataValue::DataValue(double value) :
    _type(DataValueType::Number),
    _any(value)
{
}

DataValue::DataValue(const Vector2& value) :
    _type(DataValueType::Array),
    _any(DataValue::Array())
{
    DataValue::Array& elements = _any.as<DataValue::Array>();
    elements.push_back(value.x);
    elements.push_back(value.y);
}

DataValue::DataValue(const Vector3& value) :
    _type(DataValueType::Array),
    _any(DataValue::Array())
{
    DataValue::Array& elements = _any.as<DataValue::Array>();
    elements.push_back(value.x);
    elements.push_back(value.y);
    elements.push_back(value.z);
}

DataValue::DataValue(const Vector4& value) :
    _type(DataValueType::Array),
    _any(DataValue::Array())
{
    DataValue::Array& elements = _any.as<DataValue::Array>();
    elements.push_back(value.x);
    elements.push_back(value.y);
    elements.push_back(value.z);
    elements.push_back(value.w);
}

DataValue::DataValue(const Matrix4& value) :
    _type(DataValueType::Array),
    _any(DataValue::Array())
{
    DataValue::Array& elements = _any.as<DataValue::Array>();
    for (unsigned i = 0; i < 16; ++i)
    {
        elements.push_back(value[i]);
    }
}

DataValue::DataValue(const Quaternion& value) :
    _type(DataValueType::Array),
    _any(DataValue::Array())
{
    DataValue::Array& elements = _any.as<DataValue::Array>();
    elements.push_back(value.x);
    elements.push_back(value.y);
    elements.push_back(value.z);
    elements.push_back(value.w);
}

DataValue::DataValue(const char* value) :
    _type(DataValueType::String),
    _any(std::string(value))
{
}

DataValue::DataValue(const std::string& value) :
    _type(DataValueType::String),
    _any(value)
{
}

DataValue::DataValue(const DataValue& dataValue) :
    _type(dataValue._type),
    _any(dataValue._any)
{
}

DataValue::DataValue(DataValue&& dataValue) :
    _type(dataValue._type),
    _any(std::move(dataValue._any))
{
    dataValue._type = DataValueType::Null;
}

DataValueType DataValue::type() const
{
    return _type;
}

const DataValue& DataValue::orDefault(const DataValue& dataValue) const
{
    if (isNull())
    {
        return dataValue;
    }
    else
    {
        return *this;
    }
}

bool DataValue::isNull() const
{
    return _type == DataValueType::Null;
}

bool DataValue::isBool() const
{
    return _type == DataValueType::Bool;
}

bool DataValue::isNumber() const
{
    return _type == DataValueType::Number;
}

bool DataValue::isString() const
{
    return _type == DataValueType::String;
}

bool DataValue::isArray() const
{
    return _type == DataValueType::Array;
}

bool DataValue::isObject() const
{
    return _type == DataValueType::Object;
}

bool DataValue::asBool() const
{
    if (isBool())
    {
        return _any.as<bool>();
    }
    else
    {
        return false;
    }
}

int DataValue::asInt() const
{
    if (isNumber())
    {
        return (int)_any.as<double>();
    }
    else
    {
        return 0;
    }
}

unsigned DataValue::asUnsigned() const
{
    if (isNumber())
    {
        return (unsigned)_any.as<double>();
    }
    else
    {
        return 0;
    }
}

double DataValue::asDouble() const
{
    if (isNumber())
    {
        return _any.as<double>();
    }
    else
    {
        return 0.0;
    }
}

Vector2 DataValue::asVector2() const
{
    Vector2 result;

    size_t i = 0;
    for (const DataValue& component : *this)
    {
        if (i < 2)
        {
            result[i++] = component.asDouble();
        }
        else
        {
            break;
        }
    }

    return result;
}

Vector3 DataValue::asVector3() const
{
    Vector3 result;

    size_t i = 0;
    for (const DataValue& component : *this)
    {
        if (i < 3)
        {
            result[i++] = component.asDouble();
        }
        else
        {
            break;
        }
    }

    return result;
}

Vector4 DataValue::asVector4() const
{
    Vector4 result;

    size_t i = 0;
    for (const DataValue& component : *this)
    {
        if (i < 4)
        {
            result[i++] = component.asDouble();
        }
        else
        {
            break;
        }
    }

    return result;
}

Matrix4 DataValue::asMatrix4() const
{
    Matrix4 result;

    size_t i = 0;
    for (const DataValue& component : *this)
    {
        if (i < 16)
        {
            result[i++] = component.asDouble();
        }
        else
        {
            break;
        }
    }

    return result;
}

Quaternion DataValue::asQuaternion() const
{
    Quaternion result;

    size_t i = 0;
    for (const DataValue& component : *this)
    {
        if (i < 4)
        {
            result[i++] = component.asDouble();
        }
        else
        {
            break;
        }
    }

    return result;
}

const std::string& DataValue::asString() const
{
    static std::string empty;

    if (isString())
    {
        return _any.as<std::string>();
    }
    else
    {
        return empty;
    }
}

size_t DataValue::size() const
{
    if (isArray())
    {
        return _any.as<DataValue::Array>().size();
    }
    else if (isObject())
    {
        return _any.as<DataValue::Object>().size();
    }

    return 0;
}

std::vector<std::string> DataValue::memberNames() const
{
    if (isObject())
    {
        std::vector<std::string> result;
        for (auto& pair : _any.as<DataValue::Object>())
        {
            result.push_back(pair.first);
        }
        return result;
    }
    else
    {
        return std::vector<std::string>();
    }
}

void DataValue::addMember(const std::string& name, const DataValue& dataValue)
{
    if (isObject())
    {
        _any.as<DataValue::Object>()[name] = dataValue;
    }
    else
    {
        throw InvalidOperation("The data value is not an object");
    }
}

void DataValue::addElement(const DataValue& dataValue)
{
    if (isArray())
    {
        _any.as<DataValue::Array>().push_back(dataValue);
    }
    else
    {
        throw InvalidOperation("The data value is not an array");
    }
}

const DataValue& DataValue::operator[](size_t index) const
{
    if (isArray())
    {
        const Array& array = _any.as<DataValue::Array>();
        if (index < array.size())
        {
            return array[index];
        }
        else
        {
            return _null;
        }
    }
    else
    {
        return _null;
    }
}

const DataValue& DataValue::operator[](const std::string& name) const
{
    if (isObject())
    {
        const DataValue::Object& members = _any.as<DataValue::Object>();
        auto it = members.find(name);
        if (it == members.end())
        {
            return _null;
        }
        return (*it).second;
    }
    else
    {
        return _null;
    }
}

DataValue& DataValue::operator=(const DataValue& dataValue)
{
    _type = dataValue._type;
    _any = dataValue._any;
    return *this;
}

DataValue& DataValue::operator=(DataValue&& dataValue)
{
    _type = dataValue._type;
    _any = std::move(dataValue._any);
    return *this;
}

DataValue::Array::const_iterator DataValue::begin() const
{
    if (isArray())
    {
        return _any.as<DataValue::Array>().begin();
    }
    else
    {
        return _emptyArray.begin();
    }
}

DataValue::Array::const_iterator DataValue::end() const
{
    if (isArray())
    {
        return _any.as<DataValue::Array>().end();
    }
    else
    {
        return _emptyArray.end();
    }
}

namespace hect
{

// Converts a YAML node to a DataValue
DataValue fromYaml(yaml_document_t* document, yaml_node_t* node)
{
    assert(document);
    assert(node);

    switch (node->type)
    {
    case YAML_SCALAR_NODE:
    {
        const char* value = reinterpret_cast<const char*>(node->data.scalar.value);
        std::string string(value);

        // Check if it is a bool
        if (string == "true" || string == "false")
        {
            bool boolValue = string == "true";
            return DataValue(boolValue);
        }
        else
        {
            // Attempt to parse a double from the value
            char* end = nullptr;
            double numberValue = std::strtod(string.c_str(), &end);
            if (end && *end == '\0')
            {
                // It is a valid number
                return DataValue(numberValue);
            }
            else
            {
                // Otherwise it is just a string
                return DataValue(string);
            }
        }
    }
    case YAML_SEQUENCE_NODE:
    {
        DataValue dataValue(DataValueType::Array);

        // For each item in the sequence
        for (yaml_node_item_t* item = node->data.sequence.items.start;
                item < node->data.sequence.items.top; item++)
        {
            // Convert the item to a DataValue
            yaml_node_t* itemNode = yaml_document_get_node(document, *item);
            DataValue element = fromYaml(document, itemNode);

            // Add the element
            dataValue.addElement(element);
        }

        return dataValue;
    }
    case YAML_MAPPING_NODE:
    {
        DataValue dataValue(DataValueType::Object);

        // For each pair in the mapping
        for (yaml_node_pair_t* pair = node->data.mapping.pairs.start;
                pair < node->data.mapping.pairs.top; pair++)
        {
            // Get the name from the pair
            yaml_node_t* keyNode = yaml_document_get_node(document, pair->key);
            const char* name = reinterpret_cast<const char*>(keyNode->data.scalar.value);

            // Convert the value node to a DataValue
            yaml_node_t* valueNode = yaml_document_get_node(document, pair->value);
            DataValue value = fromYaml(document, valueNode);

            // Add the member
            dataValue.addMember(name, value);
        }

        return dataValue;
    }
    default:
        return DataValue();
    }
}

}

void DataValue::decodeFromYaml(const std::string& yaml)
{
    // Initialize the parser
    yaml_parser_t parser;
    yaml_parser_initialize(&parser);
    yaml_parser_set_input_string(&parser, reinterpret_cast<const unsigned char*>(yaml.c_str()), yaml.size());

    // Attempt to parse the document
    yaml_document_t document;
    std::string errorMessage;
    if (!yaml_parser_load(&parser, &document))
    {
        // Remember the error message
        errorMessage = format("Invalid YAML: %s on line %i column %i", parser.problem, parser.problem_mark.line, parser.problem_mark.column);
    }

    if (errorMessage.empty())
    {
        yaml_node_t* node = yaml_document_get_root_node(&document);
        if (node)
        {
            // Convert all nodes recursively
            *this = fromYaml(&document, node);
        }
    }

    // Clean up document and parser
    yaml_document_delete(&document);
    yaml_parser_delete(&parser);

    // Throw the error if there was one
    if (!errorMessage.empty())
    {
        throw DecodeError(errorMessage);
    }
}

void DataValue::decodeFromYaml(ReadStream& stream)
{
    decodeFromYaml(stream.readAllToString());
}
<|endoftext|>


<commit_before><commit_msg>Fix crash on object duplication<commit_after><|endoftext|>


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

/*! \file scatter.inl
 *  \brief Inline file for scatter.h
 */

#pragma once

#include <thrust/iterator/iterator_traits.h>
#include <thrust/detail/device/cuda/vectorize.h>
#include <thrust/detail/device/dereference.h>

namespace thrust
{

namespace detail
{

namespace device
{

namespace detail
{

//////////////
// Functors //
//////////////
template <typename InputIterator1, typename InputIterator2, typename RandomAccessIterator>
struct scatter_functor
{
    InputIterator1 first;
    InputIterator2 map;
    RandomAccessIterator output;

    scatter_functor(InputIterator1 _first, InputIterator2 _map, RandomAccessIterator _output)
        : first(_first), map(_map), output(_output) {}

    template <typename IntegerType>
        __device__
        void operator()(const IntegerType& i)
        {
            //output[map[i]] = input[i];
            thrust::detail::device::dereference(output, thrust::detail::device::dereference(map, i)) = thrust::detail::device::dereference(first, i);
        }
}; // end scatter_functor

template <typename InputIterator1, typename InputIterator2, typename InputIterator3, typename RandomAccessIterator, typename Predicate>
struct scatter_if_functor
{
    InputIterator1 first;
    InputIterator2 map;
    InputIterator3 stencil;
    RandomAccessIterator output;
    Predicate pred;

    scatter_if_functor(InputIterator1 _first, InputIterator2 _map, InputIterator3 _stencil, RandomAccessIterator _output, Predicate _pred)
        : first(_first), map(_map), stencil(_stencil), output(_output), pred(_pred) {}

    template <typename IntegerType>
        __device__
        void operator()(const IntegerType& i)
        {
            //if(pred(stencil[i]))
            //    output[map[i]] = input[i];
            if(pred(thrust::detail::device::dereference(stencil, i)))
                thrust::detail::device::dereference(output, thrust::detail::device::dereference(map, i)) = thrust::detail::device::dereference(first, i);
        }
}; // end scatter_if_functor

} // end detail

template<typename InputIterator1,
         typename InputIterator2,
         typename RandomAccessIterator>
  void scatter(InputIterator1 first,
               InputIterator1 last,
               InputIterator2 map,
               RandomAccessIterator output)
{
    detail::scatter_functor<InputIterator1, InputIterator2, RandomAccessIterator> func(first, map, output);
    thrust::detail::device::cuda::vectorize(last - first, func);
} // end scatter()

template<typename InputIterator1,
         typename InputIterator2,
         typename InputIterator3,
         typename RandomAccessIterator,
         typename Predicate>
  void scatter_if(InputIterator1 first,
                  InputIterator1 last,
                  InputIterator2 map,
                  InputIterator3 stencil,
                  RandomAccessIterator output,
                  Predicate pred)
{
    detail::scatter_if_functor<InputIterator1, InputIterator2, InputIterator3, RandomAccessIterator, Predicate> func(first, map, stencil, output, pred);
    thrust::detail::device::cuda::vectorize(last - first, func);
} // end scatter_if()

} // end namespace device

} // end namespace detail

} // end namespace thrust

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

/*! \file scatter.inl
 *  \brief Inline file for scatter.h
 */

#pragma once

#include <thrust/detail/device/dereference.h>
#include <thrust/detail/device/for_each.h>
#include <thrust/tuple.h>
#include <thrust/iterator/zip_iterator.h>
#include <thrust/distance.h>

namespace thrust
{

namespace detail
{

namespace device
{

// XXX WAR circluar #inclusion with this forward declaration
template<typename InputIterator, typename UnaryFunction> void for_each(InputIterator, InputIterator, UnaryFunction);

namespace detail
{

template <typename RandomAccessIterator>
struct scatter_functor
{
  RandomAccessIterator output;

  scatter_functor(RandomAccessIterator _output)
    : output(_output) {}

  template <typename Tuple>
  __device__
  void operator()(Tuple t)
  {
    thrust::detail::device::dereference(output, thrust::get<1>(t)) = thrust::get<0>(t);
  }
}; // end scatter_functor

template <typename RandomAccessIterator, typename Predicate>
struct scatter_if_functor
{
  RandomAccessIterator output;
  Predicate pred;

  scatter_if_functor(RandomAccessIterator _output, Predicate _pred)
    : output(_output), pred(_pred) {}

  template <typename Tuple>
  __device__
  void operator()(Tuple t)
  {
    if(pred(thrust::get<2>(t)))
      thrust::detail::device::dereference(output, thrust::get<1>(t)) = thrust::get<0>(t);
  }
}; // end scatter_if_functor

} // end detail

template<typename InputIterator1,
         typename InputIterator2,
         typename RandomAccessIterator>
  void scatter(InputIterator1 first,
               InputIterator1 last,
               InputIterator2 map,
               RandomAccessIterator output)
{
  detail::scatter_functor<RandomAccessIterator> func(output);
  thrust::detail::device::for_each(thrust::make_zip_iterator(make_tuple(first, map)),
                                   thrust::make_zip_iterator(make_tuple(last,  map + thrust::distance(first, last))),
                                   func);
} // end scatter()

template<typename InputIterator1,
         typename InputIterator2,
         typename InputIterator3,
         typename RandomAccessIterator,
         typename Predicate>
  void scatter_if(InputIterator1 first,
                  InputIterator1 last,
                  InputIterator2 map,
                  InputIterator3 stencil,
                  RandomAccessIterator output,
                  Predicate pred)
{
  detail::scatter_if_functor<RandomAccessIterator, Predicate> func(output, pred);
  thrust::detail::device::for_each(thrust::make_zip_iterator(make_tuple(first, map, stencil)),
                                   thrust::make_zip_iterator(make_tuple(last,  map + thrust::distance(first, last), stencil + thrust::distance(first, last))),
                                   func);
} // end scatter_if()

} // end namespace device

} // end namespace detail

} // end namespace thrust

<|endoftext|>


<commit_before>#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <string>
#include <iostream>
using namespace std;

int main(int _argc, char *_argv[])
{
	if (_argc < 4)
	{
		cerr << "Generator: No n or m or valBorder provided" << endl;
		return -1;
	}
	srand(stoi(_argv[1]) + 1);
	int t = (rand()%stoi(string(_argv[2]))) + 1;
	int nBorder = (rand()%stoi(string(_argv[3]))) + 1;
	int valBorder = (rand()%stoi(string(_argv[4]))) + 1;
	printf("%d\n", t);
	while (t--)
	{
		int n = (rand()%nBorder) + 1;
		printf("%d\n", n);
		for (int i = 1; i <= n; ++i)
		{
			printf("%d %d\n", (rand()%valBorder) - (rand()%valBorder), (rand()%valBorder) - (rand()%valBorder));
		}
		puts("");
	}
	return 0;
}
<commit_msg>description fix<commit_after>#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <string>
#include <iostream>
using namespace std;

int main(int _argc, char *_argv[])
{
	if (_argc < 4)
	{
		cerr << "Generator: No t or nBorder or valBorder provided" << endl;
		return -1;
	}
	srand(stoi(_argv[1]) + 1);
	int t = (rand()%stoi(string(_argv[2]))) + 1;
	int nBorder = (rand()%stoi(string(_argv[3]))) + 1;
	int valBorder = (rand()%stoi(string(_argv[4]))) + 1;
	printf("%d\n", t);
	while (t--)
	{
		int n = (rand()%nBorder) + 1;
		printf("%d\n", n);
		for (int i = 1; i <= n; ++i)
		{
			printf("%d %d\n", (rand()%valBorder) - (rand()%valBorder), (rand()%valBorder) - (rand()%valBorder));
		}
		puts("");
	}
	return 0;
}
<|endoftext|>


<commit_before><commit_msg>Do not keep pointer to deleted TTree in TMVA::MethodCategory<commit_after><|endoftext|>


<commit_before>//
//  main.cpp
//  Unit Tests
//
//  Created by Evan McCartney-Melstad on 12/31/14.
//  Copyright (c) 2014 Evan McCartney-Melstad. All rights reserved.
//

#define CATCH_CONFIG_MAIN  // This tells Catch to provide a main() - only do this in one cpp file
#include "../cPWP/generateSimulatedData.h"
#include "../cPWP/bamsToPWP.h"
#include "catch.hpp"
#include <string>

/*
TEST_CASE( "Simulated reads are generated", "[generateReads]" ) {
    // Make sure that the read simulation finishes
    REQUIRE( generateReadsAndMap(1, 0.01, "0.0", "300", "50", "1000000", "100", "1234", "scaffold_0.fasta") == 0);
}
 */

TEST_CASE( "Generate reference genome for simulation tests", "[generateReference]") {
    REQUIRE( createReferenceGenome(10000000, 0.42668722, "simulatedReferenceGenome.fasta") == 0 );
}

TEST_CASE( "Generate mutated reference genomes and simulate reads", "[genomeAndReadSim]") {
    REQUIRE( generateReadsAndMap(2, 0.01, "300", "25", "20", "100", "1234", "simulatedReferenceGenome.fasta", "10") == 0);
}

TEST_CASE( "Run ANGSD on simulated reads", "[runANGSD]" ) {
    REQUIRE( runANGSDforReadCounts("bamlist.txt", "angsdOut", "10", "angsdOutLog.txt") == 0);
}

TEST_CASE( "Convert ANGSD read counts to unsigned chars for major and minor counts", "[convertCountsToBinary]") {
    REQUIRE( convertANGSDcountsToBinary("angsdOut", "angsdOut.readCounts.binary", 3, 5000) == 0); // 3 individuals, not 2, because generateReadsAndMap actually generates n+1 individuals, since one individual is identical to the reference genome. And 5000 as a max because we don't want to exclude any loci for this test
}

TEST_CASE( "Calculate PWP from the binary representations of the ANGSD readcounts", "[calcPWP]") {
    REQUIRE( calcPWPfromBinaryFile ("angsdOut.readCounts.binary", 74963, 3) == 0);
}
<commit_msg>Up depth for simulation verification<commit_after>//
//  main.cpp
//  Unit Tests
//
//  Created by Evan McCartney-Melstad on 12/31/14.
//  Copyright (c) 2014 Evan McCartney-Melstad. All rights reserved.
//

#define CATCH_CONFIG_MAIN  // This tells Catch to provide a main() - only do this in one cpp file
#include "../cPWP/generateSimulatedData.h"
#include "../cPWP/bamsToPWP.h"
#include "catch.hpp"
#include <string>

/*
TEST_CASE( "Simulated reads are generated", "[generateReads]" ) {
    // Make sure that the read simulation finishes
    REQUIRE( generateReadsAndMap(1, 0.01, "0.0", "300", "50", "1000000", "100", "1234", "scaffold_0.fasta") == 0);
}
 */

TEST_CASE( "Generate reference genome for simulation tests", "[generateReference]") {
    REQUIRE( createReferenceGenome(10000000, 0.42668722, "simulatedReferenceGenome.fasta") == 0 );
}

TEST_CASE( "Generate mutated reference genomes and simulate reads", "[genomeAndReadSim]") {
    REQUIRE( generateReadsAndMap(2, 0.01, "300", "25", "100", "100", "1234", "simulatedReferenceGenome.fasta", "10") == 0);
}

TEST_CASE( "Run ANGSD on simulated reads", "[runANGSD]" ) {
    REQUIRE( runANGSDforReadCounts("bamlist.txt", "angsdOut", "10", "angsdOutLog.txt") == 0);
}

TEST_CASE( "Convert ANGSD read counts to unsigned chars for major and minor counts", "[convertCountsToBinary]") {
    REQUIRE( convertANGSDcountsToBinary("angsdOut", "angsdOut.readCounts.binary", 3, 5000) == 0); // 3 individuals, not 2, because generateReadsAndMap actually generates n+1 individuals, since one individual is identical to the reference genome. And 5000 as a max because we don't want to exclude any loci for this test
}

TEST_CASE( "Calculate PWP from the binary representations of the ANGSD readcounts", "[calcPWP]") {
    REQUIRE( calcPWPfromBinaryFile ("angsdOut.readCounts.binary", 74963, 3) == 0);
}
<|endoftext|>


<commit_before>//=============================================================================
// ■ GDrawable.cpp
//-----------------------------------------------------------------------------
//   VMDE中GDrawable的控制与类。
//=============================================================================

#include "global.hpp"

void GDrawable::renderOnce() {
	VMSC::ChangeVertexArray(data.VAO);
	glDrawElements(GL_TRIANGLES, data.ind_c, GL_UNSIGNED_INT, 0);
}

void GDrawable::render() {
	VMSC::ChangeVertexArray(data.VAO);
	glDrawElementsInstanced(
		GL_TRIANGLES, data.ind_c, GL_UNSIGNED_INT, 0, data.mat_c);
}

void GDrawable::fbind() {
	VMSC::ChangeVertexArray(data.VAO);
	VMSC::ChangeElementArrayBuffer(data.EBO);
	glBufferData(GL_ELEMENT_ARRAY_BUFFER, data.ind_c * sizeof(GLuint), data.indices, GL_STATIC_DRAW);

	const size_t vec4Size = sizeof(glm::vec4);
	const size_t vertex_size = sizeof(Vertex); // X,Y,Z,  R,G,B,A,  S,T, Normal
	if (VMDE->gl_ver == GL_43) {
		// GL43 Vertex Attribute Format & Binding
		VMSC::ChangeArrayBuffer(data.VBO);
		glBufferData(GL_ARRAY_BUFFER, data.vtx_c * vertex_size, (GLfloat*) data.vertices, GL_STATIC_DRAW);

		glVertexAttribFormat(0, 3, GL_FLOAT, false, 0); // XYZ
		glVertexAttribFormat(1, 4, GL_FLOAT, false, 3 * sizeof(GLfloat)); // RGBA
		glVertexAttribFormat(2, 2, GL_FLOAT, false, 7 * sizeof(GLfloat)); // ST
		glVertexAttribFormat(3, 3, GL_FLOAT, false, 9 * sizeof(GLfloat)); // Normal
		glVertexAttribBinding(0, 0); // XYZ -> stream 0
		glVertexAttribBinding(1, 0); // RGBA -> stream 0
		glVertexAttribBinding(2, 0); // ST -> stream 0
		glVertexAttribBinding(3, 0); // Normal -> stream 0

		glBindVertexBuffer(0, data.VBO, 0, vertex_size);
	} else {
		// GL33 Vertex Attribute Pointer
		VMSC::ChangeArrayBuffer(data.VBO);
		glBufferData(GL_ARRAY_BUFFER, data.vtx_c * vertex_size, data.vertices, GL_STATIC_DRAW);

		glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, vertex_size, (GLvoid*) 0);
		glVertexAttribPointer(1, 4, GL_FLOAT, GL_FALSE, vertex_size, (GLvoid*) (3 * sizeof(GLfloat)));
		glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, vertex_size, (GLvoid*) (7 * sizeof(GLfloat)));
		glVertexAttribPointer(3, 3, GL_FLOAT, GL_FALSE, vertex_size, (GLvoid*) (9 * sizeof(GLfloat)));
	}
	// GL33 Vertex Attribute Pointer Instanced
	VMSC::ChangeArrayBuffer(data.MBO);
	glBufferData(GL_ARRAY_BUFFER, data.mat_c * sizeof(glm::mat4), data.mat, GL_DYNAMIC_DRAW);

	glVertexAttribPointer(4, 4, GL_FLOAT, GL_FALSE, 4 * vec4Size, (GLvoid*) 0);
	glVertexAttribPointer(5, 4, GL_FLOAT, GL_FALSE, 4 * vec4Size, (GLvoid*) (vec4Size));
	glVertexAttribPointer(6, 4, GL_FLOAT, GL_FALSE, 4 * vec4Size, (GLvoid*) (2 * vec4Size));
	glVertexAttribPointer(7, 4, GL_FLOAT, GL_FALSE, 4 * vec4Size, (GLvoid*) (3 * vec4Size));

	glEnableVertexAttribArray(0);
	glEnableVertexAttribArray(1);
	glEnableVertexAttribArray(2);
	glEnableVertexAttribArray(3);
	glEnableVertexAttribArray(4);
	glEnableVertexAttribArray(5);
	glEnableVertexAttribArray(6);
	glEnableVertexAttribArray(7);

	glVertexAttribDivisor(4, 1);
	glVertexAttribDivisor(5, 1);
	glVertexAttribDivisor(6, 1);
	glVertexAttribDivisor(7, 1);

	//glBindBuffer(GL_ARRAY_BUFFER, 0);
	//glBindVertexArray(0);
}

#define INSTANCE_UPDATE VMSC::ChangeVertexArray(data.MBO); \
	glBufferSubData(GL_ARRAY_BUFFER, 0, data.mat_c * sizeof(glm::mat4), data.mat);

void GDrawable::update() {
	VMSC::ChangeVertexArray(data.VAO);

	VMSC::ChangeArrayBuffer(data.VBO);
	//void* bufv = glMapBuffer(GL_ARRAY_BUFFER, GL_STATIC_DRAW);
	//memcpy(bufv, data.vertices, data.vtx_c * sizeof(GLfloat));
	glBufferSubData(GL_ARRAY_BUFFER, 0, data.vtx_c * sizeof(Vertex), data.vertices);
	//glUnmapBuffer(GL_ARRAY_BUFFER);

	VMSC::ChangeElementArrayBuffer(data.EBO);
	//void* bufi = glMapBuffer(GL_ELEMENT_ARRAY_BUFFER, GL_STATIC_DRAW);
	//memcpy(bufi, data.indices, data.ind_c * sizeof(GLuint));
	glBufferSubData(GL_ELEMENT_ARRAY_BUFFER, 0, data.ind_c * sizeof(GLuint), data.indices);
	//glUnmapBuffer(GL_ELEMENT_ARRAY_BUFFER);

	INSTANCE_UPDATE

	//glBindBuffer(GL_ARRAY_BUFFER,0);
}

void GDrawable::update_instance() {
	VMSC::ChangeVertexArray(data.VAO);
	INSTANCE_UPDATE
	//glBindBuffer(GL_ARRAY_BUFFER,0);
}

void GDrawable::update_instance_alien_size() {
	VMSC::ChangeVertexArray(data.VAO);
	VMSC::ChangeArrayBuffer(data.MBO);
	glBufferData(GL_ARRAY_BUFFER, data.mat_c * sizeof(glm::mat4), data.mat, GL_DYNAMIC_DRAW);
	//glBindBuffer(GL_ARRAY_BUFFER,0);
}

GDrawable::~GDrawable() {
	glDeleteVertexArrays(1, &data.VAO);
	glDeleteBuffers(1, &data.VBO);
	glDeleteBuffers(1, &data.EBO);
	glDeleteBuffers(1, &data.MBO);
}

GDrawable::GDrawable() {
	glGenVertexArrays(1, &data.VAO);
	glGenBuffers(1, &data.VBO);
	glGenBuffers(1, &data.EBO);
	glGenBuffers(1, &data.MBO);
	data.vertices = NULL;
	data.indices = NULL;
	data.mat = NULL;
}
<commit_msg>清理代码<commit_after>//=============================================================================
// ■ GDrawable.cpp
//-----------------------------------------------------------------------------
//   VMDE中GDrawable的控制与类。
//=============================================================================

#include "global.hpp"

void GDrawable::renderOnce() {
	VMSC::ChangeVertexArray(data.VAO);
	glDrawElements(GL_TRIANGLES, data.ind_c, GL_UNSIGNED_INT, 0);
}

void GDrawable::render() {
	VMSC::ChangeVertexArray(data.VAO);
	glDrawElementsInstanced(
		GL_TRIANGLES, data.ind_c, GL_UNSIGNED_INT, 0, data.mat_c);
}

void GDrawable::fbind() {
	VMSC::ChangeVertexArray(data.VAO);
	VMSC::ChangeElementArrayBuffer(data.EBO);
	glBufferData(GL_ELEMENT_ARRAY_BUFFER, data.ind_c * sizeof(GLuint), data.indices, GL_STATIC_DRAW);

	const size_t vec4Size = sizeof(glm::vec4);
	const size_t vertex_size = sizeof(Vertex); // X,Y,Z,  R,G,B,A,  S,T, Normal
	if (VMDE->gl_ver == GL_43) {
		// GL43 Vertex Attribute Format & Binding
		VMSC::ChangeArrayBuffer(data.VBO);
		glBufferData(GL_ARRAY_BUFFER, data.vtx_c * vertex_size, (GLfloat*) data.vertices, GL_STATIC_DRAW);

		glVertexAttribFormat(0, 3, GL_FLOAT, false, 0); // XYZ
		glVertexAttribFormat(1, 4, GL_FLOAT, false, 3 * sizeof(GLfloat)); // RGBA
		glVertexAttribFormat(2, 2, GL_FLOAT, false, 7 * sizeof(GLfloat)); // ST
		glVertexAttribFormat(3, 3, GL_FLOAT, false, 9 * sizeof(GLfloat)); // Normal
		glVertexAttribBinding(0, 0); // XYZ -> stream 0
		glVertexAttribBinding(1, 0); // RGBA -> stream 0
		glVertexAttribBinding(2, 0); // ST -> stream 0
		glVertexAttribBinding(3, 0); // Normal -> stream 0

		glBindVertexBuffer(0, data.VBO, 0, vertex_size);
	} else {
		// GL33 Vertex Attribute Pointer
		VMSC::ChangeArrayBuffer(data.VBO);
		glBufferData(GL_ARRAY_BUFFER, data.vtx_c * vertex_size, data.vertices, GL_STATIC_DRAW);

		glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, vertex_size, (GLvoid*) 0);
		glVertexAttribPointer(1, 4, GL_FLOAT, GL_FALSE, vertex_size, (GLvoid*) (3 * sizeof(GLfloat)));
		glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, vertex_size, (GLvoid*) (7 * sizeof(GLfloat)));
		glVertexAttribPointer(3, 3, GL_FLOAT, GL_FALSE, vertex_size, (GLvoid*) (9 * sizeof(GLfloat)));
	}
	// GL33 Vertex Attribute Pointer Instanced
	VMSC::ChangeArrayBuffer(data.MBO);
	glBufferData(GL_ARRAY_BUFFER, data.mat_c * sizeof(glm::mat4), data.mat, GL_DYNAMIC_DRAW);

	glVertexAttribPointer(4, 4, GL_FLOAT, GL_FALSE, 4 * vec4Size, (GLvoid*) 0);
	glVertexAttribPointer(5, 4, GL_FLOAT, GL_FALSE, 4 * vec4Size, (GLvoid*) (vec4Size));
	glVertexAttribPointer(6, 4, GL_FLOAT, GL_FALSE, 4 * vec4Size, (GLvoid*) (2 * vec4Size));
	glVertexAttribPointer(7, 4, GL_FLOAT, GL_FALSE, 4 * vec4Size, (GLvoid*) (3 * vec4Size));

	glEnableVertexAttribArray(0);
	glEnableVertexAttribArray(1);
	glEnableVertexAttribArray(2);
	glEnableVertexAttribArray(3);
	glEnableVertexAttribArray(4);
	glEnableVertexAttribArray(5);
	glEnableVertexAttribArray(6);
	glEnableVertexAttribArray(7);

	glVertexAttribDivisor(4, 1);
	glVertexAttribDivisor(5, 1);
	glVertexAttribDivisor(6, 1);
	glVertexAttribDivisor(7, 1);

	//glBindBuffer(GL_ARRAY_BUFFER, 0);
	//glBindVertexArray(0);
}

#define INSTANCE_UPDATE VMSC::ChangeVertexArray(data.MBO); \
	glBufferSubData(GL_ARRAY_BUFFER, 0, data.mat_c * sizeof(glm::mat4), data.mat);

void GDrawable::update() {
	VMSC::ChangeVertexArray(data.VAO);

	VMSC::ChangeArrayBuffer(data.VBO);
	glBufferSubData(GL_ARRAY_BUFFER, 0, data.vtx_c * sizeof(Vertex), data.vertices);

	VMSC::ChangeElementArrayBuffer(data.EBO);
	glBufferSubData(GL_ELEMENT_ARRAY_BUFFER, 0, data.ind_c * sizeof(GLuint), data.indices);

	INSTANCE_UPDATE

	//glBindBuffer(GL_ARRAY_BUFFER,0);
}

void GDrawable::update_instance() {
	VMSC::ChangeVertexArray(data.VAO);
	INSTANCE_UPDATE
	//glBindBuffer(GL_ARRAY_BUFFER,0);
}

void GDrawable::update_instance_alien_size() {
	VMSC::ChangeVertexArray(data.VAO);
	VMSC::ChangeArrayBuffer(data.MBO);
	glBufferData(GL_ARRAY_BUFFER, data.mat_c * sizeof(glm::mat4), data.mat, GL_DYNAMIC_DRAW);
	//glBindBuffer(GL_ARRAY_BUFFER,0);
}

GDrawable::~GDrawable() {
	glDeleteVertexArrays(1, &data.VAO);
	glDeleteBuffers(1, &data.VBO);
	glDeleteBuffers(1, &data.EBO);
	glDeleteBuffers(1, &data.MBO);
}

GDrawable::GDrawable() {
	glGenVertexArrays(1, &data.VAO);
	glGenBuffers(1, &data.VBO);
	glGenBuffers(1, &data.EBO);
	glGenBuffers(1, &data.MBO);
	data.vertices = NULL;
	data.indices = NULL;
	data.mat = NULL;
}
<|endoftext|>


<commit_before>#ifndef ANY_HPP
# define ANY_HPP
# pragma once

#include <cassert>

#include <cstdint>

#include <stdexcept>

#include <typeinfo>

#include <type_traits>

#include <utility>

namespace generic
{

class any
{
public:
  template <typename T>
  using remove_cvr = ::std::remove_cv<
    typename ::std::remove_reference<T>::type
  >;

  using typeid_t = ::std::uintptr_t;

  template <typename T>
  struct S
  {
    static constexpr char const c{};
  };

  template <typename T>
  static constexpr typeid_t type_id() noexcept
  {
    return typeid_t(&S<T>::c);
  }

  any() = default;

  any(any const& other) :
    content(other.content ? other.content->cloner_(other.content) : nullptr)
  {
  }

  any(any&& other) noexcept { *this = ::std::move(other); }

  template<typename ValueType,
    typename = typename ::std::enable_if<
      !::std::is_same<
        any, typename ::std::decay<ValueType>::type
      >{}
    >::type
  >
  any(ValueType&& value) :
    content(new holder<typename remove_cvr<ValueType>::type>(
      ::std::forward<ValueType>(value)))
  {
  }

  ~any() { delete content; }

public: // modifiers
  void clear() { swap(any()); }

  bool empty() const noexcept { return !*this; }

  void swap(any& other) noexcept { ::std::swap(content, other.content); }

  void swap(any&& other) noexcept { ::std::swap(content, other.content); }

  any& operator=(any const& rhs)
  {
    return content == rhs.content ? *this : *this = any(rhs);
  }

  any& operator=(any&& rhs) noexcept { swap(rhs); return *this; }

  template<typename ValueType,
    typename = typename ::std::enable_if<
      !::std::is_same<
        any, typename ::std::decay<ValueType>::type
      >{}
    >::type
  >
  any& operator=(ValueType&& rhs)
  {
    return *this = any(::std::forward<ValueType>(rhs));
  }

public: // queries

  explicit operator bool() const noexcept { return content; }

  typeid_t type_id() const noexcept
  {
    return *this ? content->type_id_ : typeid_t(nullptr);
  }

  auto type() const noexcept -> decltype(type_id()) { return type_id(); }

public: // get

private: // types

  template <typename T>
  static constexpr T* begin(T& value) noexcept
  {
    return &value;
  }

  template <typename T, ::std::size_t N>
  static constexpr typename ::std::remove_all_extents<T>::type*
  begin(T (&array)[N]) noexcept
  {
    return begin(*array);
  }

  template <typename T>
  static constexpr T* end(T& value) noexcept
  {
    return &value + 1;
  }

  template <typename T, ::std::size_t N>
  static constexpr typename ::std::remove_all_extents<T>::type*
  end(T (&array)[N]) noexcept
  {
    return end(array[N - 1]);
  }

  struct placeholder
  {
    typeid_t const type_id_;

    placeholder* (* const cloner_)(placeholder*);

    virtual ~placeholder() = default;

  protected:

    placeholder(typeid_t const ti, decltype(cloner_) const c) noexcept :
      type_id_(ti),
      cloner_(c)
    {
    }
  };

  template <typename ValueType>
  struct holder : public placeholder
  {
  public: // constructor
    template <class T, typename U = ValueType>
    holder(T&& value,
      typename ::std::enable_if<
        !::std::is_array<U>{} &&
        !::std::is_copy_constructible<U>{}
      >::type* = nullptr) :
      placeholder(type_id<ValueType>(), throwing_cloner),
      held(::std::forward<T>(value))
    {
    }

    template <class T, typename U = ValueType>
    holder(T&& value,
      typename ::std::enable_if<
        !::std::is_array<U>{} &&
        ::std::is_copy_constructible<U>{}
      >::type* = nullptr) :
      placeholder(type_id<ValueType>(), cloner),
      held(::std::forward<T>(value))
    {
    }

    template <class T, typename U = ValueType>
    holder(T&& value,
      typename ::std::enable_if<
        ::std::is_array<U>{} &&
        ::std::is_move_assignable<
          typename ::std::remove_const<
            typename ::std::remove_all_extents<U>::type
          >::type
        >{} &&
        ::std::is_rvalue_reference<T&&>{}
      >::type* = nullptr) :
      placeholder(type_id<ValueType>(), throwing_cloner)
    {
      ::std::copy(::std::make_move_iterator(begin(value)),
        ::std::make_move_iterator(end(value)),
        begin(held));
    }

    template <class T, typename U = ValueType>
    holder(T&& value,
      typename ::std::enable_if<
        ::std::is_array<U>{} &&
        ::std::is_copy_assignable<
          typename ::std::remove_const<
            typename ::std::remove_all_extents<U>::type
          >::type
        >{} &&
        !::std::is_rvalue_reference<T&&>{}
      >::type* = nullptr) :
      placeholder(type_id<ValueType>(), cloner)
    {
      ::std::copy(begin(value), end(value), begin(held));
    }

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

    static placeholder* cloner(placeholder* const base)
    {
      return new holder<ValueType>(static_cast<holder*>(base)->held);
    }

    static placeholder* throwing_cloner(placeholder* const)
    {
      throw ::std::logic_error("");
    }

  public:
    typename ::std::remove_const<ValueType>::type held;
  };

private: // representation

  template<typename ValueType>
  friend ValueType* any_cast(any*) noexcept;

  template<typename ValueType>
  friend ValueType* unsafe_any_cast(any*) noexcept;

#ifdef NDEBUG
  template <typename U> friend U& get(any&) noexcept;
  template <typename U> friend U const& get(any const&) noexcept;
#else
  template <typename U> friend U& get(any&);
  template <typename U> friend U const& get(any const&);
#endif // NDEBUG

  placeholder* content{};
};

template<typename ValueType>
inline ValueType* unsafe_any_cast(any* const operand) noexcept
{
  return &static_cast<any::holder<ValueType>*>(operand->content)->held;
}

template<typename ValueType>
inline ValueType const* unsafe_any_cast(any const* const operand) noexcept
{
  return unsafe_any_cast<ValueType>(const_cast<any*>(operand));
}

template<typename ValueType>
inline ValueType* any_cast(any* const operand) noexcept
{
  return operand &&
    (operand->type_id() ==
      any::type_id<typename any::remove_cvr<ValueType>::type>()) ?
    &static_cast<any::holder<ValueType>*>(operand->content)->held :
    nullptr;
}

template<typename ValueType>
inline ValueType const* any_cast(any const* const operand) noexcept
{
  return any_cast<ValueType>(const_cast<any*>(operand));
}

template<typename ValueType>
inline ValueType any_cast(any& operand)
#ifdef NDEBUG
  noexcept
#endif
{
  using nonref = typename any::remove_cvr<ValueType>::type;

#ifndef NDEBUG
  auto const result(any_cast<nonref>(&operand));

  if (result)
  {
    return *result;
  }
  else
  {
    throw ::std::bad_cast();
  }
#else
  return *unsafe_any_cast<nonref>(&operand);
#endif // NDEBUG
}

template<typename ValueType>
inline ValueType any_cast(any const& operand) noexcept(
  noexcept(
    any_cast<typename any::remove_cvr<ValueType>::type>(
      const_cast<any&>(operand)
    )
  )
)
{
  using nonref = typename any::remove_cvr<ValueType>::type;

  return any_cast<nonref const&>(const_cast<any&>(operand));
}

template <typename U>
U& get(any& a)
#ifdef NDEBUG
  noexcept
#endif
{
  using nonref = typename ::generic::any::remove_cvr<U>::type;

#ifndef NDEBUG
  if (a.content && (a.type_id() == a.type_id<nonref>()))
  {
    return static_cast<any::holder<nonref>*>(a.content)->held;
  }
  else
  {
    throw ::std::bad_cast();
  }
#else
  return static_cast<any::holder<nonref>*>(a.content)->held;
#endif // NDEBUG
}

template <typename U>
U const& get(any const& a)
#ifdef NDEBUG
  noexcept
#endif
{
  using nonref = typename ::generic::any::remove_cvr<U>::type;

#ifndef NDEBUG
  if (a.content && (a.type_id() == a.type_id<nonref>()))
  {
    return static_cast<any::holder<nonref const>*>(a.content)->held;
  }
  else
  {
    throw ::std::bad_cast();
  }
#else
  return static_cast<any::holder<nonref>*>(a.content)->held;
#endif // NDEBUG
}

template <typename U>
typename ::std::enable_if<
  !(::std::is_enum<U>{} || ::std::is_fundamental<U>{}),
  U const&
>::type
cget(any const& a) noexcept(
  noexcept(get<U const&>(::std::declval<any const>())))
{
  return get<U const&>(a);
}

template <typename U>
typename ::std::enable_if<
  ::std::is_enum<U>{} || ::std::is_fundamental<U>{},
  U
>::type
cget(any const& a) noexcept(
  noexcept(get<U>(::std::declval<any const>())))
{
  return get<U>();
}

}

#endif // ANY_HPP
<commit_msg>some fixes<commit_after>#ifndef ANY_HPP
# define ANY_HPP
# pragma once

#include <cassert>

#include <cstdint>

#include <stdexcept>

#include <typeinfo>

#include <type_traits>

#include <utility>

namespace generic
{

class any
{
public:
  template <typename T>
  using remove_cvr = ::std::remove_cv<
    typename ::std::remove_reference<T>::type
  >;

  using typeid_t = ::std::uintptr_t;

  template <typename T>
  static constexpr char const c{};

  template <typename T>
  static constexpr typeid_t type_id() noexcept
  {
    return typeid_t(&c<T>);
  }

  any() = default;

  any(any const& other) :
    content(other.content ? other.content->cloner_(other.content) : nullptr)
  {
  }

  any(any&& other) noexcept { *this = ::std::move(other); }

  template<typename ValueType,
    typename = typename ::std::enable_if<
      !::std::is_same<
        any, typename ::std::decay<ValueType>::type
      >{}
    >::type
  >
  any(ValueType&& value) :
    content(new holder<typename remove_cvr<ValueType>::type>(
      ::std::forward<ValueType>(value)))
  {
  }

  ~any() { delete content; }

public: // modifiers
  void clear() { swap(any()); }

  bool empty() const noexcept { return !*this; }

  void swap(any& other) noexcept { ::std::swap(content, other.content); }

  void swap(any&& other) noexcept { ::std::swap(content, other.content); }

  any& operator=(any const& rhs)
  {
    return content == rhs.content ? *this : *this = any(rhs);
  }

  any& operator=(any&& rhs) noexcept { swap(rhs); return *this; }

  template<typename ValueType,
    typename = typename ::std::enable_if<
      !::std::is_same<
        any, typename ::std::decay<ValueType>::type
      >{}
    >::type
  >
  any& operator=(ValueType&& rhs)
  {
    return *this = any(::std::forward<ValueType>(rhs));
  }

public: // queries

  explicit operator bool() const noexcept { return content; }

  typeid_t type_id() const noexcept
  {
    return *this ? content->type_id_ : typeid_t(nullptr);
  }

  auto type() const noexcept -> decltype(type_id()) { return type_id(); }

public: // get

private: // types

  template <typename T>
  static constexpr T* begin(T& value) noexcept
  {
    return &value;
  }

  template <typename T, ::std::size_t N>
  static constexpr typename ::std::remove_all_extents<T>::type*
  begin(T (&array)[N]) noexcept
  {
    return begin(*array);
  }

  template <typename T>
  static constexpr T* end(T& value) noexcept
  {
    return &value + 1;
  }

  template <typename T, ::std::size_t N>
  static constexpr typename ::std::remove_all_extents<T>::type*
  end(T (&array)[N]) noexcept
  {
    return end(array[N - 1]);
  }

  struct placeholder
  {
    typeid_t const type_id_;

    placeholder* (* const cloner_)(placeholder*);

    virtual ~placeholder() = default;

  protected:

    placeholder(typeid_t const ti, decltype(cloner_) const c) noexcept :
      type_id_(ti),
      cloner_(c)
    {
    }
  };

  template <typename ValueType>
  struct holder : public placeholder
  {
  public: // constructor
    template <class T, typename U = ValueType>
    holder(T&& value,
      typename ::std::enable_if<
        !::std::is_array<U>{} &&
        !::std::is_copy_constructible<U>{}
      >::type* = nullptr) :
      placeholder(type_id<ValueType>(), throwing_cloner),
      held(::std::forward<T>(value))
    {
    }

    template <class T, typename U = ValueType>
    holder(T&& value,
      typename ::std::enable_if<
        !::std::is_array<U>{} &&
        ::std::is_copy_constructible<U>{}
      >::type* = nullptr) :
      placeholder(type_id<ValueType>(), cloner),
      held(::std::forward<T>(value))
    {
    }

    template <class T, typename U = ValueType>
    holder(T&& value,
      typename ::std::enable_if<
        ::std::is_array<U>{} &&
        ::std::is_move_assignable<
          typename ::std::remove_const<
            typename ::std::remove_all_extents<U>::type
          >::type
        >{} &&
        ::std::is_rvalue_reference<T&&>{}
      >::type* = nullptr) :
      placeholder(type_id<ValueType>(), throwing_cloner)
    {
      ::std::copy(::std::make_move_iterator(begin(value)),
        ::std::make_move_iterator(end(value)),
        begin(held));
    }

    template <class T, typename U = ValueType>
    holder(T&& value,
      typename ::std::enable_if<
        ::std::is_array<U>{} &&
        ::std::is_copy_assignable<
          typename ::std::remove_const<
            typename ::std::remove_all_extents<U>::type
          >::type
        >{} &&
        !::std::is_rvalue_reference<T&&>{}
      >::type* = nullptr) :
      placeholder(type_id<ValueType>(), cloner)
    {
      ::std::copy(begin(value), end(value), begin(held));
    }

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

    static placeholder* cloner(placeholder* const base)
    {
      return new holder<ValueType>(static_cast<holder*>(base)->held);
    }

    static placeholder* throwing_cloner(placeholder* const)
    {
      throw ::std::logic_error("");
    }

  public:
    typename ::std::remove_const<ValueType>::type held;
  };

private: // representation

  template<typename ValueType>
  friend ValueType* any_cast(any*) noexcept;

  template<typename ValueType>
  friend ValueType* unsafe_any_cast(any*) noexcept;

#ifdef NDEBUG
  template <typename U> friend U& get(any&) noexcept;
  template <typename U> friend U const& get(any const&) noexcept;
#else
  template <typename U> friend U& get(any&);
  template <typename U> friend U const& get(any const&);
#endif // NDEBUG

  placeholder* content{};
};

template<typename ValueType>
inline ValueType* unsafe_any_cast(any* const operand) noexcept
{
  return &static_cast<any::holder<ValueType>*>(operand->content)->held;
}

template<typename ValueType>
inline ValueType const* unsafe_any_cast(any const* const operand) noexcept
{
  return unsafe_any_cast<ValueType>(const_cast<any*>(operand));
}

template<typename ValueType>
inline ValueType* any_cast(any* const operand) noexcept
{
  return operand &&
    (operand->type_id() ==
      any::type_id<typename any::remove_cvr<ValueType>::type>()) ?
    &static_cast<any::holder<ValueType>*>(operand->content)->held :
    nullptr;
}

template<typename ValueType>
inline ValueType const* any_cast(any const* const operand) noexcept
{
  return any_cast<ValueType>(const_cast<any*>(operand));
}

template<typename ValueType>
inline ValueType any_cast(any& operand)
#ifdef NDEBUG
  noexcept
#endif
{
  using nonref = typename any::remove_cvr<ValueType>::type;

#ifndef NDEBUG
  auto const result(any_cast<nonref>(&operand));

  if (result)
  {
    return *result;
  }
  else
  {
    throw ::std::bad_cast();
  }
#else
  return *unsafe_any_cast<nonref>(&operand);
#endif // NDEBUG
}

template<typename ValueType>
inline ValueType any_cast(any const& operand) noexcept(
  noexcept(
    any_cast<typename any::remove_cvr<ValueType>::type>(
      const_cast<any&>(operand)
    )
  )
)
{
  using nonref = typename any::remove_cvr<ValueType>::type;

  return any_cast<nonref const&>(const_cast<any&>(operand));
}

template <typename U>
U& get(any& a)
#ifdef NDEBUG
  noexcept
#endif
{
  using nonref = typename ::generic::any::remove_cvr<U>::type;

#ifndef NDEBUG
  if (a.content && (a.type_id() == a.type_id<nonref>()))
  {
    return static_cast<any::holder<nonref>*>(a.content)->held;
  }
  else
  {
    throw ::std::bad_cast();
  }
#else
  return static_cast<any::holder<nonref>*>(a.content)->held;
#endif // NDEBUG
}

template <typename U>
U const& get(any const& a)
#ifdef NDEBUG
  noexcept
#endif
{
  using nonref = typename ::generic::any::remove_cvr<U>::type;

#ifndef NDEBUG
  if (a.content && (a.type_id() == a.type_id<nonref>()))
  {
    return static_cast<any::holder<nonref const>*>(a.content)->held;
  }
  else
  {
    throw ::std::bad_cast();
  }
#else
  return static_cast<any::holder<nonref>*>(a.content)->held;
#endif // NDEBUG
}

template <typename U>
typename ::std::enable_if<
  !(::std::is_enum<U>{} || ::std::is_fundamental<U>{}),
  U const&
>::type
cget(any const& a) noexcept(
  noexcept(get<U const&>(::std::declval<any const>())))
{
  return get<U const&>(a);
}

template <typename U>
typename ::std::enable_if<
  ::std::is_enum<U>{} || ::std::is_fundamental<U>{},
  U
>::type
cget(any const& a) noexcept(
  noexcept(get<U>(::std::declval<any const>())))
{
  return get<U>();
}

}

#endif // ANY_HPP
<|endoftext|>


<commit_before><commit_msg>make dbaccess ByteString free<commit_after><|endoftext|>


<commit_before>/*
  Copyright 2007 Google Inc.

  Licensed under the Apache License, Version 2.0 (the "License");
  you may not use this file except in compliance with the License.
  You may obtain a copy of the License at

       http://www.apache.org/licenses/LICENSE-2.0

  Unless required by applicable law or agreed to in writing, software
  distributed under the License is distributed on an "AS IS" BASIS,
  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  See the License for the specific language governing permissions and
  limitations under the License.
*/

#include "js_script_context.h"
#include "ggadget/common.h"
#include "ggadget/scoped_ptr.h"
#include "ggadget/slot.h"
#include "converter.h"
#include "native_js_wrapper.h"

namespace ggadget {

const uint32 kDefaultContextSize = 64 * 1024 * 1024;
const uint32 kDefaultStackTrunkSize = 4096;

JSScriptRuntime::JSScriptRuntime()
    : runtime_(JS_NewRuntime(kDefaultContextSize)) {
  // TODO: deal with errors in release build.
  ASSERT(runtime_);
  JS_SetRuntimePrivate(runtime_, this);
}

ScriptContextInterface *JSScriptRuntime::CreateContext() {
  ASSERT(runtime_);
  JSContext *context = JS_NewContext(runtime_, kDefaultStackTrunkSize);
  ASSERT(context);
  if (!context)
    return NULL;
  JS_SetErrorReporter(context, ReportError);
  return new JSScriptContext(context);
}

void JSScriptRuntime::DestroyContext(ScriptContextInterface *context) {
  ASSERT(context);
  JSScriptContext *js_script_context = down_cast<JSScriptContext *>(context);
  JS_DestroyContext(js_script_context->context());
  delete js_script_context;
}

void JSScriptRuntime::Destroy() {
  ASSERT(runtime_);
  JS_DestroyRuntime(runtime_);
  delete this;
}

Connection *JSScriptRuntime::ConnectErrorReporter(ErrorReporter *reporter) {
  return error_reporter_signal_.Connect(reporter);
}

void JSScriptRuntime::ReportError(JSContext *cx, const char *message,
                                  JSErrorReport *report) {
  JSRuntime *js_runtime = JS_GetRuntime(cx);
  ASSERT(js_runtime);
  JSScriptRuntime *runtime = reinterpret_cast<JSScriptRuntime *>
      (JS_GetRuntimePrivate(js_runtime));
  ASSERT(runtime);

  char lineno_buf[16];
  snprintf(lineno_buf, sizeof(lineno_buf), "%d", report->lineno);
  std::string error_report(report->filename);
  error_report += ':';
  error_report += lineno_buf;
  error_report += ": ";
  error_report += message;
  runtime->error_reporter_signal_(error_report.c_str());
}

/**
 * A Slot that wraps a JavaScript function object.
 */
class JSFunctionSlot : public Slot {
 public:
  JSFunctionSlot(const Slot *prototype,
                 JSContext *context,
                 jsval function_val);
  virtual ~JSFunctionSlot();

  virtual Variant Call(int argc, Variant argv[]);

  virtual bool HasMetadata() const { return prototype_ != NULL; }
  virtual Variant::Type GetReturnType() const {
    return prototype_ ? prototype_->GetReturnType() : Variant::TYPE_VOID;
  }
  virtual int GetArgCount() const {
    return prototype_ ? prototype_->GetArgCount() : 0;
  }
  virtual const Variant::Type *GetArgTypes() const {
    return prototype_ ? prototype_->GetArgTypes() : NULL;
  }
  virtual bool operator==(const Slot &another) const {
    return function_val_ ==
           down_cast<const JSFunctionSlot *>(&another)->function_val_;
  }

 private:
  const Slot *prototype_;
  JSContext *context_;
  jsval function_val_;
  bool has_last_return_;
  Variant last_return_;
};

JSFunctionSlot::JSFunctionSlot(const Slot *prototype,
                               JSContext *context,
                               jsval function_val)
    : prototype_(prototype),
      context_(context),
      function_val_(function_val) {
  // Add a reference to the function object to prevent it from being GC'ed.
  JS_AddRoot(context_, &function_val_);
}

JSFunctionSlot::~JSFunctionSlot() {
  JS_RemoveRoot(context_, &function_val_);
}

Variant JSFunctionSlot::Call(int argc, Variant argv[]) {
  scoped_array<jsval> js_args;
  Variant return_value(GetReturnType());
  if (argc > 0) {
    js_args.reset(new jsval[argc]);
    for (int i = 0; i < argc; i++) {
      if (!ConvertNativeToJS(context_, argv[i], &js_args[i])) {
        JS_ReportError(context_, "Failed to convert argument %d (%s) to jsval",
                       i, argv[i].ToString().c_str());
        return return_value;
      }
    }
  }

  jsval rval;
  JSBool result = JS_CallFunctionValue(context_, NULL, function_val_,
                                       argc, js_args.get(), &rval);
  if (result) {
    result = ConvertJSToNative(context_, return_value, rval, &return_value);
    if (!result)
      JS_ReportError(context_, "Failed to convert jsval to native");
  }
  return return_value;
}

JSScriptContext::JSScriptContext(JSContext *context)
    : context_(context),
      filename_(NULL),
      lineno_(0) {
  JS_SetContextPrivate(context_, this);
  // JS_SetOptions(context_, JS_GetOptions(context_) | JSOPTION_STRICT);
}

JSScriptContext::~JSScriptContext() {
  // Don't destroy context_, because it is not owned by me.
}

static JSScriptContext *GetJSScriptContext(JSContext *context) {
  return reinterpret_cast<JSScriptContext *>(JS_GetContextPrivate(context));
}

// As we don't want to depend on only the public SpiderMonkey APIs, the only
// way to get the current filename and lineno is from the JSErrorReport.
void JSScriptContext::RecordFileAndLine(JSContext *cx, const char *message,
                                        JSErrorReport *report) {
  JSScriptContext *context = GetJSScriptContext(cx);
  if (context) {
    context->filename_ = report->filename;
    context->lineno_ = report->lineno;
  }
}

void JSScriptContext::GetCurrentFileAndLineInternal(const char **filename,
                                                    int *lineno) {
  filename_ = NULL;
  lineno_ = 0;
  JSErrorReporter old_reporter = JS_SetErrorReporter(context_,
                                                     RecordFileAndLine);
  // Let the JavaScript engine call RecordFileAndLine.
  JS_ReportError(context_, "");
  JS_SetErrorReporter(context_, old_reporter);
  *filename = filename_;
  *lineno = lineno_;
}

void JSScriptContext::GetCurrentFileAndLine(JSContext *context,
                                            const char **filename,
                                            int *lineno) {
  JSScriptContext *context_wrapper = GetJSScriptContext(context);
  if (context_wrapper) {
    context_wrapper->GetCurrentFileAndLineInternal(filename, lineno);
  } else {
    *filename = NULL;
    *lineno = 0;
  }
}

JSObject *JSScriptContext::WrapNativeObjectToJSInternal(
    ScriptableInterface *scriptable) {
  ASSERT(scriptable);
  WrapperMap::const_iterator it = wrapper_map_.find(scriptable);
  if (it == wrapper_map_.end()) {
    NativeJSWrapper *wrapper = new NativeJSWrapper(context_, scriptable);
    wrapper_map_[scriptable] = wrapper;
    ASSERT(wrapper->scriptable() == scriptable);
    return wrapper->js_object();
  } else {
    return it->second->js_object();
  }
}

JSObject *JSScriptContext::WrapNativeObjectToJS(
    JSContext *cx, ScriptableInterface *scriptable) {
  JSScriptContext *context_wrapper = GetJSScriptContext(cx);
  ASSERT(context_wrapper);
  if (context_wrapper)
    return context_wrapper->WrapNativeObjectToJSInternal(scriptable);
  return NULL;
}

void JSScriptContext::FinalizeNativeJSWrapperInternal(
    NativeJSWrapper *wrapper) {
  wrapper_map_.erase(wrapper->scriptable());
}

void JSScriptContext::FinalizeNativeJSWrapper(JSContext *cx,
                                              NativeJSWrapper *wrapper) {
  JSScriptContext *context_wrapper = GetJSScriptContext(cx);
  ASSERT(context_wrapper);
  if (context_wrapper)
    context_wrapper->FinalizeNativeJSWrapperInternal(wrapper);
}

jsval JSScriptContext::ConvertSlotToJSInternal(Slot *slot) {
  ASSERT(slot);
  SlotJSMap::const_iterator it = slot_js_map_.find(slot);
  if (it != slot_js_map_.end()) {
    // If found, it->second JavaScript function object that has been wrapped
    // into a JSFunctionSlot.
    return it->second;
  }
  // We don't allow JavaScript to call native slot in this way.
  return JSVAL_NULL;
}

jsval JSScriptContext::ConvertSlotToJS(JSContext *cx, Slot *slot) {
  JSScriptContext *context_wrapper = GetJSScriptContext(cx);
  ASSERT(context_wrapper);
  if (context_wrapper)
    return context_wrapper->ConvertSlotToJSInternal(slot);
  return JSVAL_NULL;
}

JSBool JSScriptContext::CallNativeSlot(JSContext *cx, JSObject *obj,
                                       uintN argc, jsval *argv, jsval *rval) {
  // According to JS stack structure, argv[-2] is the current function object.
  JSObject *func_object = JSVAL_TO_OBJECT(argv[-2]);
  // Get the method slot from the reserved slot.
  jsval val;
  if (!JS_GetReservedSlot(cx, func_object, 0, &val) ||
      !JSVAL_IS_INT(val))
    return JS_FALSE;
  Slot *slot = reinterpret_cast<Slot *>(JSVAL_TO_PRIVATE(val));

  const Variant::Type *arg_types = NULL;
  if (slot->HasMetadata()) {
    if (argc != static_cast<uintN>(slot->GetArgCount())) {
      // Argc mismatch.
      JS_ReportError(cx, "Wrong number of arguments: %d. %d expected",
                     argc, slot->GetArgCount());
      return JS_FALSE;
    }
    arg_types = slot->GetArgTypes();
  }

  scoped_array<Variant> params;
  if (argc > 0) {
    params.reset(new Variant[argc]);
    for (uintN i = 0; i < argc; i++) {
      JSBool result = arg_types != NULL ?
          ConvertJSToNative(cx, Variant(arg_types[i]), argv[i], &params[i]) :
          ConvertJSToNativeVariant(cx, argv[i], &params[i]);
      if (!result) {
        JS_ReportError(cx, "Failed to convert argument %d to native", i);
        return JS_FALSE;
      }
    }
  }

  Variant return_value = slot->Call(argc, params.get());
  JSBool result = ConvertNativeToJS(cx, return_value, rval);
  if (!result)
    JS_ReportError(cx, "Failed to convert result (%s) to jsval",
                   return_value.ToString().c_str());
  return result;
}

Slot *JSScriptContext::NewJSFunctionSlotInternal(const Slot *prototype,
                                                 jsval function_val) {
  Slot *slot = new JSFunctionSlot(prototype, context_, function_val);
  // Put it here to make it possible for ConvertNativeSlotToJS to unwrap
  // a JSFunctionSlot.
  slot_js_map_[slot] = function_val;
  return slot;
}

Slot *JSScriptContext::NewJSFunctionSlot(JSContext *cx,
                                         const Slot *prototype,
                                         jsval function_val) {
  JSScriptContext *context_wrapper = GetJSScriptContext(cx);
  ASSERT(context_wrapper);
  if (context_wrapper)
    return context_wrapper->NewJSFunctionSlotInternal(prototype, function_val);
  return NULL;
}

Slot *JSScriptContext::Compile(const char *script,
                               const char *filename,
                               int lineno) {
  JSFunction *function = JS_CompileFunction(
      context_, NULL, NULL, 0, NULL,  // No name and no argument.
      script, strlen(script), filename, lineno);
  if (!function)
    return NULL;

  return new JSFunctionSlot(
      NULL, context_, OBJECT_TO_JSVAL(JS_GetFunctionObject(function)));
}

bool JSScriptContext::SetValue(const char *object_expression,
                               const char *property_name,
                               Variant value) {
  JSObject *object;
  if (!object_expression) {
    object = JS_GetGlobalObject(context_);
  } else {
    jsval rval;
    if (!JS_EvaluateScript(context_, JS_GetGlobalObject(context_),
                           object_expression, strlen(object_expression),
                           NULL, 0, &rval) ||
        JSVAL_IS_NULL(rval) || !JSVAL_IS_OBJECT(rval)) {
      JS_ReportError(context_,
          "Can't evaluate '%s' or it doesn't evaluate to a non-null object",
          object_expression);
      return false;
    }
    object = JSVAL_TO_OBJECT(rval);
  }

  if (!object)
    // Should not occur.
    return false;

  jsval js_val;
  if (!ConvertNativeToJS(context_, value, &js_val)) {
    JS_ReportError(context_, "Failed to convert native value %s to JavaScript",
                   value.ToString().c_str());
    return false;
  }
  return JS_SetProperty(context_, object, property_name, &js_val);
}

bool JSScriptContext::SetGlobalObject(ScriptableInterface *global_object) {
  JSObject *js_global = WrapNativeObjectToJS(context_, global_object);
  if (!js_global)
    return false;
  return JS_InitStandardClasses(context_, js_global);
}

} // namespace ggadget
<commit_msg> r161@wangxianzhu:  wangxianzhu | 2007-08-15 17:31:10 +0800  removed useless code, and updated a comment<commit_after>/*
  Copyright 2007 Google Inc.

  Licensed under the Apache License, Version 2.0 (the "License");
  you may not use this file except in compliance with the License.
  You may obtain a copy of the License at

       http://www.apache.org/licenses/LICENSE-2.0

  Unless required by applicable law or agreed to in writing, software
  distributed under the License is distributed on an "AS IS" BASIS,
  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  See the License for the specific language governing permissions and
  limitations under the License.
*/

#include "js_script_context.h"
#include "ggadget/common.h"
#include "ggadget/scoped_ptr.h"
#include "ggadget/slot.h"
#include "converter.h"
#include "native_js_wrapper.h"

namespace ggadget {

const uint32 kDefaultContextSize = 64 * 1024 * 1024;
const uint32 kDefaultStackTrunkSize = 4096;

JSScriptRuntime::JSScriptRuntime()
    : runtime_(JS_NewRuntime(kDefaultContextSize)) {
  // TODO: deal with errors in release build.
  ASSERT(runtime_);
  JS_SetRuntimePrivate(runtime_, this);
}

ScriptContextInterface *JSScriptRuntime::CreateContext() {
  ASSERT(runtime_);
  JSContext *context = JS_NewContext(runtime_, kDefaultStackTrunkSize);
  ASSERT(context);
  if (!context)
    return NULL;
  JS_SetErrorReporter(context, ReportError);
  return new JSScriptContext(context);
}

void JSScriptRuntime::DestroyContext(ScriptContextInterface *context) {
  ASSERT(context);
  JSScriptContext *js_script_context = down_cast<JSScriptContext *>(context);
  JS_DestroyContext(js_script_context->context());
  delete js_script_context;
}

void JSScriptRuntime::Destroy() {
  ASSERT(runtime_);
  JS_DestroyRuntime(runtime_);
  delete this;
}

Connection *JSScriptRuntime::ConnectErrorReporter(ErrorReporter *reporter) {
  return error_reporter_signal_.Connect(reporter);
}

void JSScriptRuntime::ReportError(JSContext *cx, const char *message,
                                  JSErrorReport *report) {
  JSRuntime *js_runtime = JS_GetRuntime(cx);
  ASSERT(js_runtime);
  JSScriptRuntime *runtime = reinterpret_cast<JSScriptRuntime *>
      (JS_GetRuntimePrivate(js_runtime));
  ASSERT(runtime);

  char lineno_buf[16];
  snprintf(lineno_buf, sizeof(lineno_buf), "%d", report->lineno);
  std::string error_report(report->filename);
  error_report += ':';
  error_report += lineno_buf;
  error_report += ": ";
  error_report += message;
  runtime->error_reporter_signal_(error_report.c_str());
}

/**
 * A Slot that wraps a JavaScript function object.
 */
class JSFunctionSlot : public Slot {
 public:
  JSFunctionSlot(const Slot *prototype,
                 JSContext *context,
                 jsval function_val);
  virtual ~JSFunctionSlot();

  virtual Variant Call(int argc, Variant argv[]);

  virtual bool HasMetadata() const { return prototype_ != NULL; }
  virtual Variant::Type GetReturnType() const {
    return prototype_ ? prototype_->GetReturnType() : Variant::TYPE_VOID;
  }
  virtual int GetArgCount() const {
    return prototype_ ? prototype_->GetArgCount() : 0;
  }
  virtual const Variant::Type *GetArgTypes() const {
    return prototype_ ? prototype_->GetArgTypes() : NULL;
  }
  virtual bool operator==(const Slot &another) const {
    return function_val_ ==
           down_cast<const JSFunctionSlot *>(&another)->function_val_;
  }

 private:
  const Slot *prototype_;
  JSContext *context_;
  jsval function_val_;
};

JSFunctionSlot::JSFunctionSlot(const Slot *prototype,
                               JSContext *context,
                               jsval function_val)
    : prototype_(prototype),
      context_(context),
      function_val_(function_val) {
  // Add a reference to the function object to prevent it from being GC'ed.
  JS_AddRoot(context_, &function_val_);
}

JSFunctionSlot::~JSFunctionSlot() {
  JS_RemoveRoot(context_, &function_val_);
}

Variant JSFunctionSlot::Call(int argc, Variant argv[]) {
  scoped_array<jsval> js_args;
  Variant return_value(GetReturnType());
  if (argc > 0) {
    js_args.reset(new jsval[argc]);
    for (int i = 0; i < argc; i++) {
      if (!ConvertNativeToJS(context_, argv[i], &js_args[i])) {
        JS_ReportError(context_, "Failed to convert argument %d (%s) to jsval",
                       i, argv[i].ToString().c_str());
        return return_value;
      }
    }
  }

  jsval rval;
  JSBool result = JS_CallFunctionValue(context_, NULL, function_val_,
                                       argc, js_args.get(), &rval);
  if (result) {
    result = ConvertJSToNative(context_, return_value, rval, &return_value);
    if (!result)
      JS_ReportError(context_, "Failed to convert jsval to native");
  }
  return return_value;
}

JSScriptContext::JSScriptContext(JSContext *context)
    : context_(context),
      filename_(NULL),
      lineno_(0) {
  JS_SetContextPrivate(context_, this);
  // JS_SetOptions(context_, JS_GetOptions(context_) | JSOPTION_STRICT);
}

JSScriptContext::~JSScriptContext() {
  // Don't destroy context_, because it is not owned by me.
}

static JSScriptContext *GetJSScriptContext(JSContext *context) {
  return reinterpret_cast<JSScriptContext *>(JS_GetContextPrivate(context));
}

// As we want to depend on only the public SpiderMonkey APIs, the only
// way to get the current filename and lineno is from the JSErrorReport.
void JSScriptContext::RecordFileAndLine(JSContext *cx, const char *message,
                                        JSErrorReport *report) {
  JSScriptContext *context = GetJSScriptContext(cx);
  if (context) {
    context->filename_ = report->filename;
    context->lineno_ = report->lineno;
  }
}

void JSScriptContext::GetCurrentFileAndLineInternal(const char **filename,
                                                    int *lineno) {
  filename_ = NULL;
  lineno_ = 0;
  JSErrorReporter old_reporter = JS_SetErrorReporter(context_,
                                                     RecordFileAndLine);
  // Let the JavaScript engine call RecordFileAndLine.
  JS_ReportError(context_, "");
  JS_SetErrorReporter(context_, old_reporter);
  *filename = filename_;
  *lineno = lineno_;
}

void JSScriptContext::GetCurrentFileAndLine(JSContext *context,
                                            const char **filename,
                                            int *lineno) {
  JSScriptContext *context_wrapper = GetJSScriptContext(context);
  if (context_wrapper) {
    context_wrapper->GetCurrentFileAndLineInternal(filename, lineno);
  } else {
    *filename = NULL;
    *lineno = 0;
  }
}

JSObject *JSScriptContext::WrapNativeObjectToJSInternal(
    ScriptableInterface *scriptable) {
  ASSERT(scriptable);
  WrapperMap::const_iterator it = wrapper_map_.find(scriptable);
  if (it == wrapper_map_.end()) {
    NativeJSWrapper *wrapper = new NativeJSWrapper(context_, scriptable);
    wrapper_map_[scriptable] = wrapper;
    ASSERT(wrapper->scriptable() == scriptable);
    return wrapper->js_object();
  } else {
    return it->second->js_object();
  }
}

JSObject *JSScriptContext::WrapNativeObjectToJS(
    JSContext *cx, ScriptableInterface *scriptable) {
  JSScriptContext *context_wrapper = GetJSScriptContext(cx);
  ASSERT(context_wrapper);
  if (context_wrapper)
    return context_wrapper->WrapNativeObjectToJSInternal(scriptable);
  return NULL;
}

void JSScriptContext::FinalizeNativeJSWrapperInternal(
    NativeJSWrapper *wrapper) {
  wrapper_map_.erase(wrapper->scriptable());
}

void JSScriptContext::FinalizeNativeJSWrapper(JSContext *cx,
                                              NativeJSWrapper *wrapper) {
  JSScriptContext *context_wrapper = GetJSScriptContext(cx);
  ASSERT(context_wrapper);
  if (context_wrapper)
    context_wrapper->FinalizeNativeJSWrapperInternal(wrapper);
}

jsval JSScriptContext::ConvertSlotToJSInternal(Slot *slot) {
  ASSERT(slot);
  SlotJSMap::const_iterator it = slot_js_map_.find(slot);
  if (it != slot_js_map_.end()) {
    // If found, it->second JavaScript function object that has been wrapped
    // into a JSFunctionSlot.
    return it->second;
  }
  // We don't allow JavaScript to call native slot in this way.
  return JSVAL_NULL;
}

jsval JSScriptContext::ConvertSlotToJS(JSContext *cx, Slot *slot) {
  JSScriptContext *context_wrapper = GetJSScriptContext(cx);
  ASSERT(context_wrapper);
  if (context_wrapper)
    return context_wrapper->ConvertSlotToJSInternal(slot);
  return JSVAL_NULL;
}

JSBool JSScriptContext::CallNativeSlot(JSContext *cx, JSObject *obj,
                                       uintN argc, jsval *argv, jsval *rval) {
  // According to JS stack structure, argv[-2] is the current function object.
  JSObject *func_object = JSVAL_TO_OBJECT(argv[-2]);
  // Get the method slot from the reserved slot.
  jsval val;
  if (!JS_GetReservedSlot(cx, func_object, 0, &val) ||
      !JSVAL_IS_INT(val))
    return JS_FALSE;
  Slot *slot = reinterpret_cast<Slot *>(JSVAL_TO_PRIVATE(val));

  const Variant::Type *arg_types = NULL;
  if (slot->HasMetadata()) {
    if (argc != static_cast<uintN>(slot->GetArgCount())) {
      // Argc mismatch.
      JS_ReportError(cx, "Wrong number of arguments: %d. %d expected",
                     argc, slot->GetArgCount());
      return JS_FALSE;
    }
    arg_types = slot->GetArgTypes();
  }

  scoped_array<Variant> params;
  if (argc > 0) {
    params.reset(new Variant[argc]);
    for (uintN i = 0; i < argc; i++) {
      JSBool result = arg_types != NULL ?
          ConvertJSToNative(cx, Variant(arg_types[i]), argv[i], &params[i]) :
          ConvertJSToNativeVariant(cx, argv[i], &params[i]);
      if (!result) {
        JS_ReportError(cx, "Failed to convert argument %d to native", i);
        return JS_FALSE;
      }
    }
  }

  Variant return_value = slot->Call(argc, params.get());
  JSBool result = ConvertNativeToJS(cx, return_value, rval);
  if (!result)
    JS_ReportError(cx, "Failed to convert result (%s) to jsval",
                   return_value.ToString().c_str());
  return result;
}

Slot *JSScriptContext::NewJSFunctionSlotInternal(const Slot *prototype,
                                                 jsval function_val) {
  Slot *slot = new JSFunctionSlot(prototype, context_, function_val);
  // Put it here to make it possible for ConvertNativeSlotToJS to unwrap
  // a JSFunctionSlot.
  slot_js_map_[slot] = function_val;
  return slot;
}

Slot *JSScriptContext::NewJSFunctionSlot(JSContext *cx,
                                         const Slot *prototype,
                                         jsval function_val) {
  JSScriptContext *context_wrapper = GetJSScriptContext(cx);
  ASSERT(context_wrapper);
  if (context_wrapper)
    return context_wrapper->NewJSFunctionSlotInternal(prototype, function_val);
  return NULL;
}

Slot *JSScriptContext::Compile(const char *script,
                               const char *filename,
                               int lineno) {
  JSFunction *function = JS_CompileFunction(
      context_, NULL, NULL, 0, NULL,  // No name and no argument.
      script, strlen(script), filename, lineno);
  if (!function)
    return NULL;

  return new JSFunctionSlot(
      NULL, context_, OBJECT_TO_JSVAL(JS_GetFunctionObject(function)));
}

bool JSScriptContext::SetValue(const char *object_expression,
                               const char *property_name,
                               Variant value) {
  JSObject *object;
  if (!object_expression) {
    object = JS_GetGlobalObject(context_);
  } else {
    jsval rval;
    if (!JS_EvaluateScript(context_, JS_GetGlobalObject(context_),
                           object_expression, strlen(object_expression),
                           NULL, 0, &rval) ||
        JSVAL_IS_NULL(rval) || !JSVAL_IS_OBJECT(rval)) {
      JS_ReportError(context_,
          "Can't evaluate '%s' or it doesn't evaluate to a non-null object",
          object_expression);
      return false;
    }
    object = JSVAL_TO_OBJECT(rval);
  }

  if (!object)
    // Should not occur.
    return false;

  jsval js_val;
  if (!ConvertNativeToJS(context_, value, &js_val)) {
    JS_ReportError(context_, "Failed to convert native value %s to JavaScript",
                   value.ToString().c_str());
    return false;
  }
  return JS_SetProperty(context_, object, property_name, &js_val);
}

bool JSScriptContext::SetGlobalObject(ScriptableInterface *global_object) {
  JSObject *js_global = WrapNativeObjectToJS(context_, global_object);
  if (!js_global)
    return false;
  return JS_InitStandardClasses(context_, js_global);
}

} // namespace ggadget
<|endoftext|>


<commit_before>#ifndef CELL_AUTOMATA_OPENGLWRAPPER_DRAWISING_TAITS
#define CELL_AUTOMATA_OPENGLWRAPPER_DRAWISING_TAITS

#include <string>

struct Ising_window_traits
{
    constexpr static const char* window_name = "ising_model";
    constexpr static int window_x_size = 1000;
    constexpr static int window_y_size = 1000;
    constexpr static double margin = 0.1;
};

#endif /* CELL_AUTOMATA_OPENGLWRAPPER_DRAWISING_TAITS */
<commit_msg>decide window must be square.<commit_after>#ifndef CELL_AUTOMATA_OPENGLWRAPPER_DRAWISING_TAITS
#define CELL_AUTOMATA_OPENGLWRAPPER_DRAWISING_TAITS

#include <string>

struct Ising_window_traits
{
    constexpr static const char* window_name = "ising_model";
    constexpr static int window_side = 1000;
    constexpr static double margin = 0.1;
};

#endif /* CELL_AUTOMATA_OPENGLWRAPPER_DRAWISING_TAITS */
<|endoftext|>