<commit_before>#include "precomp.h"

#include "internal/common.h"
#include "internal/enums.h"
#include "internal/node.h"
#include "internal/error.h"

namespace Spark
{
    namespace Internal
    {
        thread_local symbolid_t g_nextSymbol;
        thread_local std::vector<Spark::Node*> g_nodeStack;
        thread_local std::vector<Spark::Node*> g_allocatedNodes;

        uintptr_t isNull(char* buffer)
        {
            return buffer ? 1 : 0;
        }

        char* nullOrOffset(char* buffer, uint32_t offset)
        {
            return buffer + isNull(buffer) * offset;
        }

        template<typename... Args>
        int32_t doSnprintf(char* buffer, int32_t buffer_size, int32_t written, const Args&... args)
        {
            SPARK_ASSERT(written >= 0);
            auto len = snprintf(nullOrOffset(buffer, written),  buffer_size == 0 ? 0 : buffer_size - written, args...);
            SPARK_ASSERT(len >= 0);
            SPARK_ASSERT(buffer_size == 0 || (written + len < buffer_size));

            return written + len;
        }

        int32_t controlNodeToText(Spark::Node* node, char* buffer, int32_t buffer_size, int32_t written)
        {
            return doSnprintf(buffer, buffer_size, written,
                "%s\n",
                spark_control_to_str(node->_control));
        }

        int32_t functionNodeToText(Spark::Node* node, char* buffer, int32_t buffer_size, int32_t written)
        {
            char datatypeBuffer[32];
            return doSnprintf(buffer, buffer_size, written,
                "%s -> %s\n",
                spark_operator_to_str((operator_t)node->_function.id),
                spark_datatype_to_str(node->_function.type, datatypeBuffer, sizeof(datatypeBuffer)));
        }

        int32_t symbolNodeToText(Spark::Node* node, char* buffer, int32_t buffer_size, int32_t written)
        {
            char datatypeBuffer[32];
            return doSnprintf(buffer, buffer_size, written,
                "0x%x -> %s\n",
                node->_symbol.id,
                spark_datatype_to_str(node->_symbol.type, datatypeBuffer, sizeof(datatypeBuffer)));
        }

        int32_t constantNodeToText(Spark::Node* node, char* buffer, int32_t buffer_size, int32_t written)
        {
            const auto dt = node->_constant.type;
            const auto primitive = dt & DataType::PrimitiveMask;
            // primitive cannot be void
            SPARK_ASSERT(primitive != DataType::Void);
            const auto component = dt & DataType::ComponentMask;
            const auto container = dt & DataType::ContainerMask;
            // container cannot be init'd with a constant
            SPARK_ASSERT(container == 0);

            int32_t componentCount = 1;
            switch(component)
            {
                case DataType::Vector2:
                    componentCount = 2;
                    break;
                case DataType::Vector3:
                    componentCount = 3;
                    break;
                case DataType::Vector4:
                    componentCount = 4;
                    break;
                case DataType::Vector8:
                    componentCount = 8;
                    break;
                case DataType::Vector16:
                    componentCount = 16;
                    break;
            }

            auto raw = node->_constant.buffer;
            SPARK_ASSERT(raw != nullptr);

            for(int32_t k = 0; k < componentCount; k++)
            {
                if(k > 0)
                {
                    written = doSnprintf(buffer, buffer_size, written, "%s", ", ");
                }

                union
                {
                    int64_t signed_integer;
                    uint64_t unsigned_integer;
                    double floating_point;
                };

                switch(primitive)
                {
                    case DataType::Char:
                        signed_integer = *((int8_t*)raw + k);
                        break;
                    case DataType::UChar:
                        unsigned_integer = *((uint8_t*)raw + k);
                        break;
                    case DataType::Short:
                        signed_integer = *((int16_t*)raw + k);
                        break;
                    case DataType::UShort:
                        unsigned_integer = *((uint16_t*)raw + k);
                        break;
                    case DataType::Int:
                        signed_integer = *((int32_t*)raw + k);
                        break;
                    case DataType::UInt:
                        unsigned_integer = *((uint32_t*)raw + k);
                        break;
                    case DataType::Long:
                        signed_integer = *((int64_t*)raw + k);
                        break;
                    case DataType::ULong:
                        unsigned_integer = *((uint64_t*)raw + k);
                        break;
                    case DataType::Float:
                        floating_point = *((float*)raw + k);
                        break;
                    case DataType::Double:
                        floating_point = *((double*)raw + k);
                        break;
                }

                switch(primitive)
                {
                    case DataType::Char:
                    case DataType::Short:
                    case DataType::Int:
                    case DataType::Long:
                        written = doSnprintf(buffer, buffer_size, written, "%lli", signed_integer);
                        break;
                    case DataType::UChar:
                    case DataType::UShort:
                    case DataType::UInt:
                    case DataType::ULong:
                        written = doSnprintf(buffer, buffer_size, written, "%llu", unsigned_integer);
                        break;
                    case DataType::Float:
                    case DataType::Double:
                        written = doSnprintf(buffer, buffer_size, written, "%f", floating_point);
                        break;
                }
            }

            char datatypeBuffer[32];
            written = doSnprintf(buffer, buffer_size, written,
                " -> %s\n",
                spark_datatype_to_str(node->_symbol.type, datatypeBuffer, sizeof(datatypeBuffer)));

            return written;
        }

        int32_t propertyNodeToText(Spark::Node* node, char* buffer, int32_t buffer_size, int32_t written)
        {
            char propertyBuffer[8];
            written = doSnprintf(buffer, buffer_size, written,
                "Property::%s\n",
                spark_property_to_str(node->_property.id, propertyBuffer, countof(propertyBuffer)));
            return written;
        }

        // if out_bufer is null
        int32_t nodeToText(Spark::Node* node, char* out_buffer, int32_t buffer_size, int32_t written, int32_t indentation)
        {
            SPARK_ASSERT(node != nullptr);
            SPARK_ASSERT((out_buffer == nullptr && buffer_size == 0) || (out_buffer != nullptr && buffer_size > 0));

            // write indentation
            for(int32_t k = 0; k < indentation; k++)
            {
                written = doSnprintf(out_buffer, buffer_size, written, "%s", " ");
            }
            // write node info

            switch(node->_type)
            {
                case NodeType::Control:
                    written = controlNodeToText(node, out_buffer, buffer_size, written);
                    break;
                case NodeType::Operator:
                    written = functionNodeToText(node, out_buffer, buffer_size, written);
                    break;
                case NodeType::Symbol:
                    written = symbolNodeToText(node, out_buffer, buffer_size, written);
                    break;
                case NodeType::Constant:
                    written = constantNodeToText(node, out_buffer, buffer_size, written);
                    break;
                case NodeType::Property:
                    written = propertyNodeToText(node, out_buffer, buffer_size, written);
                    break;
                default:
                    written = doSnprintf(out_buffer, buffer_size, written, "%s\n", spark_nodetype_to_str(node->_type));
                    break;
            }

            // depth first traversal
            for(uint32_t k = 0; k < node->_childCount; k++)
            {
                Node* child = node->_children[k];
                written = nodeToText(child, out_buffer, buffer_size, written, indentation + 1);
            }

            // return characters written
            return written;
        }
    }
}

using namespace Spark;
using namespace Spark::Internal;

void spark_begin_program()
{
    g_nextSymbol = 0;
}

void spark_end_program()
{
    // free all of our unattached nodes
    for(auto node : g_allocatedNodes)
    {
        spark_free_node(node);
    }
    g_allocatedNodes.clear();
}

// symbol functions
Spark::symbolid_t spark_next_symbol()
{
    return g_nextSymbol++;
}

// node creation

Node* spark_create_control_node(control_t c)
{
    SPARK_ASSERT(c < Control::Count);

    Node* node = new Node();
    node->_children = nullptr;
    node->_childCount = 0;
    node->_bufferSize = 0;
    node->_type = NodeType::Control;
    node->_control = c;

    try
    {
        g_allocatedNodes.push_back(node);
    }
    catch(std::exception& ex)
    {
        spark_print_exception(ex);
    }

    return node;
}

Node* spark_create_operator_node(datatype_t dt, operator_t id)
{
    Node* node = new Node();
    node->_children = nullptr;
    node->_childCount = 0;
    node->_bufferSize = 0;
    node->_type = NodeType::Operator;
    node->_function.type = dt;
    node->_function.id = id;

    try
    {
        g_allocatedNodes.push_back(node);
    }
    catch(std::exception& ex)
    {
        spark_print_exception(ex);
    }

    return node;
}

Node* spark_create_symbol_node(datatype_t dt, symbolid_t id)
{
    Node* node = new Node();
    node->_children = nullptr;
    node->_childCount = 0;
    node->_bufferSize = 0;
    node->_type = NodeType::Symbol;
    node->_symbol.type = dt;
    node->_symbol.id = id;

    try
    {
        g_allocatedNodes.push_back(node);
    }
    catch(std::exception& ex)
    {
        spark_print_exception(ex);
    }

    return node;
}

Node* spark_create_constant_node(datatype_t dt, const void* raw, size_t sz)
{
    SPARK_ASSERT(raw != nullptr);
    SPARK_ASSERT(sz > 0);

    Node* node = new Node();
    node->_children = nullptr;
    node->_childCount = 0;
    node->_bufferSize = 0;
    node->_type = NodeType::Constant;
    node->_constant.type = dt;
    node->_constant.buffer = new uint8_t[sz];
    std::memcpy(node->_constant.buffer, raw, sz);
    node->_constant.size = sz;

    try
    {
        g_allocatedNodes.push_back(node);
    }
    catch(std::exception& ex)
    {
        spark_print_exception(ex);
    }

    return node;
}

Node* spark_create_property_node(property_t prop)
{
    Node* node = new Node();
    node->_children = nullptr;
    node->_childCount = 0;
    node->_bufferSize = 0;
    node->_type = NodeType::Property;
    node->_property.id = prop;

    try
    {
        g_allocatedNodes.push_back(node);
    }
    catch(std::exception& ex)
    {
        spark_print_exception(ex);
    }

    return node;
}

Node* spark_create_operator1_node(Spark::datatype_t dt, Spark::operator_t op, Spark::Node* arg1)
{
    Node* result_node = spark_create_operator_node(dt, op);
    spark_add_child_node(result_node, arg1);
    return result_node;
}

Node* spark_create_operator2_node(Spark::datatype_t dt, Spark::operator_t op, Spark::Node* arg1, Spark::Node* arg2)
{
    Node* result_node = spark_create_operator_node(dt, op);
    spark_add_child_node(result_node, arg1);
    spark_add_child_node(result_node, arg2);
    return result_node;
}

// node deletion
void spark_free_node(Node* node)
{
    delete[] node->_children;
    if(node->_type == NodeType::Constant)
    {
        delete[] node->_constant.buffer;
    }
    delete node;
}
// tree modification
void spark_add_child_node(Node* root, Node* node)
{
    SPARK_ASSERT(root != nullptr);
    SPARK_ASSERT(node != nullptr);
    SPARK_ASSERT(root != node);

    // init buffer if it is empty
    if(root->_children == nullptr)
    {
        const uint32_t bufferSize = 8;
        root->_children = new Node*[bufferSize];
        for(uint32_t k = 0; k < bufferSize; k++)
        {
            root->_children[k] = nullptr;
        }
        root->_bufferSize = bufferSize;
        root->_childCount = 0;
    }

    // add child node
    root->_children[root->_childCount++] = node;

    // resize buffer if it is full
    if(root->_childCount == root->_bufferSize)
    {
        // copy over nodes to new buffer
        const uint32_t bufferSize = root->_bufferSize * 2;
        const uint32_t childCount = root->_childCount;
        Node** children = new Node*[bufferSize];
        for(uint32_t k = 0; k < childCount; k++)
        {
            children[k] = root->_children[k];
        }

        for(uint32_t k = childCount; k < bufferSize; k++)
        {
            children[k] = nullptr;
        }

        // delete old buffer and copy over data
        delete[] root->_children;
        root->_children = children;
        root->_childCount = childCount;
        root->_bufferSize = bufferSize;
    }

    SPARK_ASSERT(root->_childCount < root->_bufferSize);
}
// source scope
void spark_push_scope_node(Node* node)
{
    try
    {
        if(g_nodeStack.size() > 0)
        {
            spark_add_child_node(g_nodeStack.back(), node);
        }
        g_nodeStack.push_back(node);
    }
    catch(std::exception& ex)
    {
        spark_print_exception(ex);
    }
}

void spark_pop_scope_node()
{
    SPARK_ASSERT(g_nodeStack.size() > 0);
    g_nodeStack.pop_back();
}

Node* spark_peek_scope_node()
{
    SPARK_ASSERT(g_nodeStack.size() > 0);
    return g_nodeStack.back();
}

Node* spark_get_root_node()
{
    SPARK_ASSERT(g_nodeStack.size() > 0);
    return g_nodeStack.front();
}

int32_t spark_node_to_text(Spark::Node* node, char* out_buffer, int32_t buffer_size)
{
    return Spark::Internal::nodeToText(node, out_buffer, buffer_size, 0, 0) + 1;
}
<commit_msg>missing node.cpp from last commit<commit_after>#include "precomp.h"

#include "internal/common.h"
#include "internal/enums.h"
#include "internal/node.h"
#include "internal/error.h"

namespace Spark
{
    namespace Internal
    {
        thread_local symbolid_t g_nextSymbol;
        thread_local std::vector<Spark::Node*> g_nodeStack;
        thread_local std::vector<Spark::Node*> g_allocatedNodes;

        uintptr_t isNull(char* buffer)
        {
            return buffer ? 1 : 0;
        }

        char* nullOrOffset(char* buffer, uint32_t offset)
        {
            return buffer + isNull(buffer) * offset;
        }

        template<typename... Args>
        int32_t doSnprintf(char* buffer, int32_t buffer_size, int32_t written, const Args&... args)
        {
            SPARK_ASSERT(written >= 0);
            auto len = snprintf(nullOrOffset(buffer, written),  buffer_size == 0 ? 0 : buffer_size - written, args...);
            SPARK_ASSERT(len >= 0);
            SPARK_ASSERT(buffer_size == 0 || (written + len < buffer_size));

            return written + len;
        }

        int32_t controlNodeToText(Spark::Node* node, char* buffer, int32_t buffer_size, int32_t written)
        {
            return doSnprintf(buffer, buffer_size, written,
                "%s\n",
                spark_control_to_str(node->_control));
        }

        int32_t functionNodeToText(Spark::Node* node, char* buffer, int32_t buffer_size, int32_t written)
        {
            char datatypeBuffer[32];
            return doSnprintf(buffer, buffer_size, written,
                "%s -> %s\n",
                spark_operator_to_str((operator_t)node->_function.id),
                spark_datatype_to_str(node->_function.type, datatypeBuffer, sizeof(datatypeBuffer)));
        }

        int32_t symbolNodeToText(Spark::Node* node, char* buffer, int32_t buffer_size, int32_t written)
        {
            char datatypeBuffer[32];
            return doSnprintf(buffer, buffer_size, written,
                "0x%x -> %s\n",
                node->_symbol.id,
                spark_datatype_to_str(node->_symbol.type, datatypeBuffer, sizeof(datatypeBuffer)));
        }

        int32_t constantNodeToText(Spark::Node* node, char* buffer, int32_t buffer_size, int32_t written)
        {
            const auto dt = node->_constant.type;
            const auto primitive = dt & DataType::PrimitiveMask;
            // primitive cannot be void
            SPARK_ASSERT(primitive != DataType::Void);
            const auto component = dt & DataType::ComponentMask;
            const auto container = dt & DataType::ContainerMask;
            // container cannot be init'd with a constant
            SPARK_ASSERT(container == 0);

            int32_t componentCount = 1;
            switch(component)
            {
                case DataType::Vector2:
                    componentCount = 2;
                    break;
                case DataType::Vector3:
                    componentCount = 3;
                    break;
                case DataType::Vector4:
                    componentCount = 4;
                    break;
                case DataType::Vector8:
                    componentCount = 8;
                    break;
                case DataType::Vector16:
                    componentCount = 16;
                    break;
            }

            auto raw = node->_constant.buffer;
            SPARK_ASSERT(raw != nullptr);

            for(int32_t k = 0; k < componentCount; k++)
            {
                if(k > 0)
                {
                    written = doSnprintf(buffer, buffer_size, written, "%s", ", ");
                }

                union
                {
                    int64_t signed_integer;
                    uint64_t unsigned_integer;
                    double floating_point;
                };

                switch(primitive)
                {
                    case DataType::Char:
                        signed_integer = *((int8_t*)raw + k);
                        break;
                    case DataType::UChar:
                        unsigned_integer = *((uint8_t*)raw + k);
                        break;
                    case DataType::Short:
                        signed_integer = *((int16_t*)raw + k);
                        break;
                    case DataType::UShort:
                        unsigned_integer = *((uint16_t*)raw + k);
                        break;
                    case DataType::Int:
                        signed_integer = *((int32_t*)raw + k);
                        break;
                    case DataType::UInt:
                        unsigned_integer = *((uint32_t*)raw + k);
                        break;
                    case DataType::Long:
                        signed_integer = *((int64_t*)raw + k);
                        break;
                    case DataType::ULong:
                        unsigned_integer = *((uint64_t*)raw + k);
                        break;
                    case DataType::Float:
                        floating_point = *((float*)raw + k);
                        break;
                    case DataType::Double:
                        floating_point = *((double*)raw + k);
                        break;
                }

                switch(primitive)
                {
                    case DataType::Char:
                    case DataType::Short:
                    case DataType::Int:
                    case DataType::Long:
                        written = doSnprintf(buffer, buffer_size, written, "%lli", signed_integer);
                        break;
                    case DataType::UChar:
                    case DataType::UShort:
                    case DataType::UInt:
                    case DataType::ULong:
                        written = doSnprintf(buffer, buffer_size, written, "%llu", unsigned_integer);
                        break;
                    case DataType::Float:
                    case DataType::Double:
                        written = doSnprintf(buffer, buffer_size, written, "%f", floating_point);
                        break;
                }
            }

            char datatypeBuffer[32];
            written = doSnprintf(buffer, buffer_size, written,
                " -> %s\n",
                spark_datatype_to_str(node->_symbol.type, datatypeBuffer, sizeof(datatypeBuffer)));

            return written;
        }

        int32_t propertyNodeToText(Spark::Node* node, char* buffer, int32_t buffer_size, int32_t written)
        {
            char propertyBuffer[8];
            written = doSnprintf(buffer, buffer_size, written,
                "Property::%s\n",
                spark_property_to_str(node->_property.id, propertyBuffer, countof(propertyBuffer)));
            return written;
        }

        // if out_bufer is null
        int32_t nodeToText(Spark::Node* node, char* out_buffer, int32_t buffer_size, int32_t written, int32_t indentation)
        {
            SPARK_ASSERT(node != nullptr);
            SPARK_ASSERT((out_buffer == nullptr && buffer_size == 0) || (out_buffer != nullptr && buffer_size > 0));

            // write indentation
            for(int32_t k = 0; k < indentation; k++)
            {
                written = doSnprintf(out_buffer, buffer_size, written, "%s", " ");
            }
            // write node info

            switch(node->_type)
            {
                case NodeType::Control:
                    written = controlNodeToText(node, out_buffer, buffer_size, written);
                    break;
                case NodeType::Operator:
                    written = functionNodeToText(node, out_buffer, buffer_size, written);
                    break;
                case NodeType::Symbol:
                    written = symbolNodeToText(node, out_buffer, buffer_size, written);
                    break;
                case NodeType::Constant:
                    written = constantNodeToText(node, out_buffer, buffer_size, written);
                    break;
                case NodeType::Property:
                    written = propertyNodeToText(node, out_buffer, buffer_size, written);
                    break;
                default:
                    written = doSnprintf(out_buffer, buffer_size, written, "%s\n", spark_nodetype_to_str(node->_type));
                    break;
            }

            // depth first traversal
            for(uint32_t k = 0; k < node->_childCount; k++)
            {
                Node* child = node->_children[k];
                written = nodeToText(child, out_buffer, buffer_size, written, indentation + 1);
            }

            // return characters written
            return written;
        }
    }
}

using namespace Spark;
using namespace Spark::Internal;

void spark_begin_program()
{
    g_nextSymbol = 0;
}

void spark_end_program()
{
    // free all of our unattached nodes
    for(auto node : g_allocatedNodes)
    {
        spark_free_node(node);
    }
    g_allocatedNodes.clear();
}

// symbol functions
Spark::symbolid_t spark_next_symbol()
{
    return g_nextSymbol++;
}

// node creation

Node* spark_create_control_node(control_t c)
{
    SPARK_ASSERT(c < Control::Count);

    Node* node = new Node();
    node->_children = nullptr;
    node->_childCount = 0;
    node->_bufferSize = 0;
    node->_type = NodeType::Control;
    node->_attached = false;
    node->_control = c;

    try
    {
        g_allocatedNodes.push_back(node);
    }
    catch(std::exception& ex)
    {
        spark_print_exception(ex);
    }

    return node;
}

Node* spark_create_operator_node(datatype_t dt, operator_t id)
{
    Node* node = new Node();
    node->_children = nullptr;
    node->_childCount = 0;
    node->_bufferSize = 0;
    node->_type = NodeType::Operator;
    node->_attached = false;
    node->_function.type = dt;
    node->_function.id = id;

    try
    {
        g_allocatedNodes.push_back(node);
    }
    catch(std::exception& ex)
    {
        spark_print_exception(ex);
    }

    return node;
}

Node* spark_create_symbol_node(datatype_t dt, symbolid_t id)
{
    Node* node = new Node();
    node->_children = nullptr;
    node->_childCount = 0;
    node->_bufferSize = 0;
    node->_type = NodeType::Symbol;
    node->_attached = false;
    node->_symbol.type = dt;
    node->_symbol.id = id;

    try
    {
        g_allocatedNodes.push_back(node);
    }
    catch(std::exception& ex)
    {
        spark_print_exception(ex);
    }

    return node;
}

Node* spark_create_constant_node(datatype_t dt, const void* raw, size_t sz)
{
    SPARK_ASSERT(raw != nullptr);
    SPARK_ASSERT(sz > 0);

    Node* node = new Node();
    node->_children = nullptr;
    node->_childCount = 0;
    node->_bufferSize = 0;
    node->_type = NodeType::Constant;
    node->_attached = false;
    node->_constant.type = dt;
    node->_constant.buffer = new uint8_t[sz];
    std::memcpy(node->_constant.buffer, raw, sz);
    node->_constant.size = sz;

    try
    {
        g_allocatedNodes.push_back(node);
    }
    catch(std::exception& ex)
    {
        spark_print_exception(ex);
    }

    return node;
}

Node* spark_create_property_node(property_t prop)
{
    Node* node = new Node();
    node->_children = nullptr;
    node->_childCount = 0;
    node->_bufferSize = 0;
    node->_attached = false;
    node->_type = NodeType::Property;
    node->_property.id = prop;

    try
    {
        g_allocatedNodes.push_back(node);
    }
    catch(std::exception& ex)
    {
        spark_print_exception(ex);
    }

    return node;
}

Node* spark_create_operator1_node(Spark::datatype_t dt, Spark::operator_t op, Spark::Node* arg1)
{
    Node* result_node = spark_create_operator_node(dt, op);
    spark_add_child_node(result_node, arg1);
    return result_node;
}

Node* spark_create_operator2_node(Spark::datatype_t dt, Spark::operator_t op, Spark::Node* arg1, Spark::Node* arg2)
{
    Node* result_node = spark_create_operator_node(dt, op);
    spark_add_child_node(result_node, arg1);
    spark_add_child_node(result_node, arg2);
    return result_node;
}

// node deletion
void spark_free_node(Node* node)
{
    delete[] node->_children;
    if(node->_type == NodeType::Constant)
    {
        delete[] node->_constant.buffer;
    }
    delete node;
}
// tree modification
void spark_add_child_node(Node* root, Node* node)
{
    SPARK_ASSERT(root != nullptr);
    SPARK_ASSERT(node != nullptr);
    SPARK_ASSERT(root != node);

    // init buffer if it is empty
    if(root->_children == nullptr)
    {
        const uint32_t bufferSize = 8;
        root->_children = new Node*[bufferSize];
        for(uint32_t k = 0; k < bufferSize; k++)
        {
            root->_children[k] = nullptr;
        }
        root->_bufferSize = bufferSize;
        root->_childCount = 0;
    }

    // add child node
    root->_children[root->_childCount++] = node;
    node->_attached = true;

    // resize buffer if it is full
    if(root->_childCount == root->_bufferSize)
    {
        // copy over nodes to new buffer
        const uint32_t bufferSize = root->_bufferSize * 2;
        const uint32_t childCount = root->_childCount;
        Node** children = new Node*[bufferSize];
        for(uint32_t k = 0; k < childCount; k++)
        {
            children[k] = root->_children[k];
        }

        for(uint32_t k = childCount; k < bufferSize; k++)
        {
            children[k] = nullptr;
        }

        // delete old buffer and copy over data
        delete[] root->_children;
        root->_children = children;
        root->_childCount = childCount;
        root->_bufferSize = bufferSize;
    }

    SPARK_ASSERT(root->_childCount < root->_bufferSize);
}
// source scope
void spark_push_scope_node(Node* node)
{
    try
    {
        if(g_nodeStack.size() > 0)
        {
            spark_add_child_node(g_nodeStack.back(), node);
        }
        g_nodeStack.push_back(node);
    }
    catch(std::exception& ex)
    {
        spark_print_exception(ex);
    }
}

void spark_pop_scope_node()
{
    SPARK_ASSERT(g_nodeStack.size() > 0);
    g_nodeStack.pop_back();
}

Node* spark_peek_scope_node()
{
    SPARK_ASSERT(g_nodeStack.size() > 0);
    return g_nodeStack.back();
}

Node* spark_get_root_node()
{
    SPARK_ASSERT(g_nodeStack.size() > 0);
    return g_nodeStack.front();
}

int32_t spark_node_to_text(Spark::Node* node, char* out_buffer, int32_t buffer_size)
{
    return Spark::Internal::nodeToText(node, out_buffer, buffer_size, 0, 0) + 1;
}
<|endoftext|>


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

#ifndef _SFX_GUISAVEAS_HXX_
#define _SFX_GUISAVEAS_HXX_

#ifndef _COM_SUN_STAR_UNO_SEQUENCE_HXX_
#include <com/sun/star/uno/Sequence.hxx>
#endif

#ifndef _COM_SUN_STAR_LANG_XMULTISERVICEFACTORY_HPP_
#include <com/sun/star/lang/XMultiServiceFactory.hpp>
#endif

#ifndef _COM_SUN_STAR_BEANS_PROPERTYVALUE_HPP_
#include <com/sun/star/beans/PropertyValue.hpp>
#endif
#ifndef _COM_SUN_STAR_BEANS_NAMEDVALUE_HPP_
#include <com/sun/star/beans/NamedValue.hpp>
#endif

#ifndef _COM_SUN_STAR_CONTAINER_XNAMEACCESS_HPP_
#include <com/sun/star/container/XNameAccess.hpp>
#endif
#ifndef _COM_SUN_STAR_CONTAINER_XCONTAINERQUERY_HPP_
#include <com/sun/star/container/XContainerQuery.hpp>
#endif

#ifndef _COM_SUN_STAR_FRAME_XMODEL_HPP_
#include <com/sun/star/frame/XModel.hpp>
#endif

#ifndef _DRAFTS_COM_SUN_STAR_FRAME_XMODULEMANAGER_HPP_
#include <drafts/com/sun/star/frame/XModuleManager.hpp>
#endif

#include <comphelper/sequenceashashmap.hxx>
#include "docinf.hxx"

class ModelData_Impl;
class SfxStoringHelper
{
    friend class ModelData_Impl;

private:
    ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory > m_xFactory;
    ::com::sun::star::uno::Reference< ::com::sun::star::container::XNameAccess > m_xFilterCFG;
    ::com::sun::star::uno::Reference< ::com::sun::star::container::XContainerQuery > m_xFilterQuery;
    ::com::sun::star::uno::Reference< ::drafts::com::sun::star::frame::XModuleManager > m_xModuleManager;
    ::com::sun::star::uno::Reference< ::com::sun::star::container::XNameAccess > m_xNamedModManager;

    ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory > GetServiceFactory();
    ::com::sun::star::uno::Reference< ::com::sun::star::container::XNameAccess > GetFilterConfiguration();
    ::com::sun::star::uno::Reference< ::com::sun::star::container::XContainerQuery > GetFilterQuery();
    ::com::sun::star::uno::Reference< ::drafts::com::sun::star::frame::XModuleManager > GetModuleManager();
    ::com::sun::star::uno::Reference< ::com::sun::star::container::XNameAccess > GetNamedModuleManager();

public:
    SfxStoringHelper( const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >& xFactory );

    sal_Bool GUIStoreModel(
                    const ::com::sun::star::uno::Reference< ::com::sun::star::frame::XModel >& xModel,
                    const ::rtl::OUString& aSlotName,
                    ::com::sun::star::uno::Sequence< ::com::sun::star::beans::PropertyValue >& aArgsSequence);

    static ::com::sun::star::uno::Sequence< ::com::sun::star::beans::PropertyValue > SearchForFilter(
                    const ::com::sun::star::uno::Reference< ::com::sun::star::container::XContainerQuery >& xFilterQuery,
                    const ::com::sun::star::uno::Sequence< ::com::sun::star::beans::NamedValue >& aSearchRequest,
                    sal_Int32 nMustFlags,
                    sal_Int32 nDontFlags );

    static sal_Bool CheckFilterOptionsAppearence(
                    const ::com::sun::star::uno::Reference< ::com::sun::star::container::XNameAccess >& xFilterCFG,
                    const ::rtl::OUString& aFilterName );

    static void FillCopy( const ::com::sun::star::uno::Reference< ::com::sun::star::frame::XModel >& xModel,
                         SfxDocumentInfo& aDocInfoToFill );

    static void PrepareDocInfoForStore( SfxDocumentInfo& aDocInfoToClear );

    static void SetDocInfoState( const ::com::sun::star::uno::Reference< ::com::sun::star::frame::XModel >& xModel,
                                const SfxDocumentInfo& aDocInfoState,
                                sal_Bool bNoModify );

    static void ExecuteInfoDlg( const ::rtl::OUString& aTargetURL,
                                const ::rtl::OUString& aTitle, const String& rBaseURL,
                                SfxDocumentInfo &aDocInfo );

    static sal_Bool WarnUnacceptableFormat(
                                    const ::com::sun::star::uno::Reference< ::com::sun::star::frame::XModel >& xModel,
                                    ::rtl::OUString aOldUIName,
                                    ::rtl::OUString aDefUIName,
                                    sal_Bool bCanProceedFurther );

    static void ExecuteFilterDialog( SfxStoringHelper& _rStorageHelper
                                    ,const ::rtl::OUString& sFilterName
                                    ,const ::com::sun::star::uno::Reference< ::com::sun::star::frame::XModel >& xModel
                                    ,/*OUT*/::com::sun::star::uno::Sequence< ::com::sun::star::beans::PropertyValue >& rArgsSequence
                                );
};

#endif

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

#ifndef _SFX_GUISAVEAS_HXX_
#define _SFX_GUISAVEAS_HXX_

#ifndef _COM_SUN_STAR_UNO_SEQUENCE_HXX_
#include <com/sun/star/uno/Sequence.hxx>
#endif

#ifndef _COM_SUN_STAR_LANG_XMULTISERVICEFACTORY_HPP_
#include <com/sun/star/lang/XMultiServiceFactory.hpp>
#endif

#ifndef _COM_SUN_STAR_BEANS_PROPERTYVALUE_HPP_
#include <com/sun/star/beans/PropertyValue.hpp>
#endif
#ifndef _COM_SUN_STAR_BEANS_NAMEDVALUE_HPP_
#include <com/sun/star/beans/NamedValue.hpp>
#endif

#ifndef _COM_SUN_STAR_CONTAINER_XNAMEACCESS_HPP_
#include <com/sun/star/container/XNameAccess.hpp>
#endif
#ifndef _COM_SUN_STAR_CONTAINER_XCONTAINERQUERY_HPP_
#include <com/sun/star/container/XContainerQuery.hpp>
#endif

#ifndef _COM_SUN_STAR_FRAME_XMODEL_HPP_
#include <com/sun/star/frame/XModel.hpp>
#endif

#ifndef _COM_SUN_STAR_FRAME_XMODULEMANAGER_HPP_
#include <com/sun/star/frame/XModuleManager.hpp>
#endif

#include <comphelper/sequenceashashmap.hxx>
#include "docinf.hxx"

class ModelData_Impl;
class SfxStoringHelper
{
    friend class ModelData_Impl;

private:
    ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory > m_xFactory;
    ::com::sun::star::uno::Reference< ::com::sun::star::container::XNameAccess > m_xFilterCFG;
    ::com::sun::star::uno::Reference< ::com::sun::star::container::XContainerQuery > m_xFilterQuery;
    ::com::sun::star::uno::Reference< ::com::sun::star::frame::XModuleManager > m_xModuleManager;
    ::com::sun::star::uno::Reference< ::com::sun::star::container::XNameAccess > m_xNamedModManager;

    ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory > GetServiceFactory();
    ::com::sun::star::uno::Reference< ::com::sun::star::container::XNameAccess > GetFilterConfiguration();
    ::com::sun::star::uno::Reference< ::com::sun::star::container::XContainerQuery > GetFilterQuery();
    ::com::sun::star::uno::Reference< ::com::sun::star::frame::XModuleManager > GetModuleManager();
    ::com::sun::star::uno::Reference< ::com::sun::star::container::XNameAccess > GetNamedModuleManager();

public:
    SfxStoringHelper( const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >& xFactory );

    sal_Bool GUIStoreModel(
                    const ::com::sun::star::uno::Reference< ::com::sun::star::frame::XModel >& xModel,
                    const ::rtl::OUString& aSlotName,
                    ::com::sun::star::uno::Sequence< ::com::sun::star::beans::PropertyValue >& aArgsSequence);

    static ::com::sun::star::uno::Sequence< ::com::sun::star::beans::PropertyValue > SearchForFilter(
                    const ::com::sun::star::uno::Reference< ::com::sun::star::container::XContainerQuery >& xFilterQuery,
                    const ::com::sun::star::uno::Sequence< ::com::sun::star::beans::NamedValue >& aSearchRequest,
                    sal_Int32 nMustFlags,
                    sal_Int32 nDontFlags );

    static sal_Bool CheckFilterOptionsAppearence(
                    const ::com::sun::star::uno::Reference< ::com::sun::star::container::XNameAccess >& xFilterCFG,
                    const ::rtl::OUString& aFilterName );

    static void FillCopy( const ::com::sun::star::uno::Reference< ::com::sun::star::frame::XModel >& xModel,
                         SfxDocumentInfo& aDocInfoToFill );

    static void PrepareDocInfoForStore( SfxDocumentInfo& aDocInfoToClear );

    static void SetDocInfoState( const ::com::sun::star::uno::Reference< ::com::sun::star::frame::XModel >& xModel,
                                const SfxDocumentInfo& aDocInfoState,
                                sal_Bool bNoModify );

    static void ExecuteInfoDlg( const ::rtl::OUString& aTargetURL,
                                const ::rtl::OUString& aTitle, const String& rBaseURL,
                                SfxDocumentInfo &aDocInfo );

    static sal_Bool WarnUnacceptableFormat(
                                    const ::com::sun::star::uno::Reference< ::com::sun::star::frame::XModel >& xModel,
                                    ::rtl::OUString aOldUIName,
                                    ::rtl::OUString aDefUIName,
                                    sal_Bool bCanProceedFurther );

    static void ExecuteFilterDialog( SfxStoringHelper& _rStorageHelper
                                    ,const ::rtl::OUString& sFilterName
                                    ,const ::com::sun::star::uno::Reference< ::com::sun::star::frame::XModel >& xModel
                                    ,/*OUT*/::com::sun::star::uno::Sequence< ::com::sun::star::beans::PropertyValue >& rArgsSequence
                                );
};

#endif

<|endoftext|>


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

#include "chrome/browser/android/banners/app_banner_settings_helper.h"

#include <string>

#include "chrome/browser/content_settings/host_content_settings_map.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/common/content_settings_pattern.h"
#include "content/public/browser/web_contents.h"
#include "url/gurl.h"

namespace {
// Max number of apps that a particular site may show a banner for.
const size_t kMaxAppsPerSite = 3;
}

bool AppBannerSettingsHelper::IsAllowed(content::WebContents* web_contents,
                                        const GURL& origin_url,
                                        const std::string& package_name) {
  Profile* profile =
      Profile::FromBrowserContext(web_contents->GetBrowserContext());
  if (profile->IsOffTheRecord() || web_contents->GetURL() != origin_url ||
      package_name.empty()) {
    return false;
  }

  // Check if this combination has been previously disabled.
  HostContentSettingsMap* settings = profile->GetHostContentSettingsMap();
  if (!settings)
    return false;
  scoped_ptr<base::Value> value(
      settings->GetWebsiteSetting(origin_url,
                                  origin_url,
                                  CONTENT_SETTINGS_TYPE_APP_BANNER,
                                  std::string(),
                                  NULL));
  if (!value.get()) {
    // We've never blocked a banner on this site.
    return true;
  } else if (value->IsType(base::Value::TYPE_DICTIONARY)) {
    // We expect to get dictionary back, where the keys are the package names.
    base::DictionaryValue* banner_dict =
        static_cast<base::DictionaryValue*>(value.get());
    bool is_allowed = false;
    if (banner_dict->GetBoolean(package_name, &is_allowed)) {
      return is_allowed;
    } else {
      return banner_dict->size() < ::kMaxAppsPerSite;
    }
  } else {
    // Somehow the value we got back is not a dictionary (e.g. the settings were
    // corrupted by malware).  Try to clear it out.
    ContentSettingsPattern pattern(ContentSettingsPattern::FromURL(origin_url));
    if (pattern.IsValid()) {
      settings->SetWebsiteSetting(pattern,
                                  ContentSettingsPattern::Wildcard(),
                                  CONTENT_SETTINGS_TYPE_APP_BANNER,
                                  std::string(),
                                  NULL);
      return true;
    }
  }

  return false;
}

void AppBannerSettingsHelper::Block(content::WebContents* web_contents,
                                    const GURL& origin_url,
                                    const std::string& package_name) {
  Profile* profile =
      Profile::FromBrowserContext(web_contents->GetBrowserContext());
  HostContentSettingsMap* settings = profile->GetHostContentSettingsMap();
  ContentSettingsPattern pattern(ContentSettingsPattern::FromURL(origin_url));
  if (!settings || !pattern.IsValid())
    return;

  scoped_ptr<base::Value> value(
      settings->GetWebsiteSetting(origin_url,
                                  origin_url,
                                  CONTENT_SETTINGS_TYPE_APP_BANNER,
                                  std::string(),
                                  NULL));
  base::DictionaryValue* banner_dict = NULL;
  if (value.get() && value->IsType(base::Value::TYPE_DICTIONARY)) {
    banner_dict = static_cast<base::DictionaryValue*>(value.release());
  } else {
    banner_dict = new base::DictionaryValue();
  }

  // Update the setting and save it back.
  banner_dict->SetBoolean(package_name, false);
  settings->SetWebsiteSetting(pattern,
                              ContentSettingsPattern::Wildcard(),
                              CONTENT_SETTINGS_TYPE_APP_BANNER,
                              std::string(),
                              banner_dict);
}
<commit_msg>Sanitize app package names for DictionaryValue<commit_after>// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/browser/android/banners/app_banner_settings_helper.h"

#include <algorithm>
#include <string>

#include "chrome/browser/content_settings/host_content_settings_map.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/common/content_settings_pattern.h"
#include "content/public/browser/web_contents.h"
#include "url/gurl.h"

namespace {
std::string SanitizePackageName(std::string package_name) {
  // DictionaryValue doesn't allow '.' in the keys.  Replace them with ' '
  // because you can't have a package name with a ' ' in it.
  std::replace(package_name.begin(), package_name.end(), '.', ' ');
  return package_name;
}

// Max number of apps that a particular site may show a banner for.
const size_t kMaxAppsPerSite = 3;
}  // namespace

bool AppBannerSettingsHelper::IsAllowed(content::WebContents* web_contents,
                                        const GURL& origin_url,
                                        const std::string& package_name) {
  std::string sanitized_package_name = SanitizePackageName(package_name);
  Profile* profile =
      Profile::FromBrowserContext(web_contents->GetBrowserContext());
  if (profile->IsOffTheRecord() || web_contents->GetURL() != origin_url ||
      sanitized_package_name.empty()) {
    return false;
  }

  // Check if this combination has been previously disabled.
  HostContentSettingsMap* settings = profile->GetHostContentSettingsMap();
  if (!settings)
    return false;
  scoped_ptr<base::Value> value(
      settings->GetWebsiteSetting(origin_url,
                                  origin_url,
                                  CONTENT_SETTINGS_TYPE_APP_BANNER,
                                  std::string(),
                                  NULL));
  if (!value.get()) {
    // We've never blocked a banner on this site.
    return true;
  } else if (value->IsType(base::Value::TYPE_DICTIONARY)) {
    // We expect to get a Dictionary back, where the keys are the package names.
    base::DictionaryValue* banner_dict =
        static_cast<base::DictionaryValue*>(value.get());
    bool is_allowed = false;
    if (banner_dict->GetBoolean(sanitized_package_name, &is_allowed)) {
      return is_allowed;
    } else {
      return banner_dict->size() < ::kMaxAppsPerSite;
    }
  } else {
    // Somehow the value we got back is not a dictionary (e.g. the settings were
    // corrupted by malware).  Try to clear it out.
    ContentSettingsPattern pattern(ContentSettingsPattern::FromURL(origin_url));
    if (pattern.IsValid()) {
      settings->SetWebsiteSetting(pattern,
                                  ContentSettingsPattern::Wildcard(),
                                  CONTENT_SETTINGS_TYPE_APP_BANNER,
                                  std::string(),
                                  NULL);
      return true;
    }
  }

  return false;
}

void AppBannerSettingsHelper::Block(content::WebContents* web_contents,
                                    const GURL& origin_url,
                                    const std::string& package_name) {
  std::string sanitized_package_name = SanitizePackageName(package_name);
  DCHECK(!sanitized_package_name.empty());

  Profile* profile =
      Profile::FromBrowserContext(web_contents->GetBrowserContext());
  HostContentSettingsMap* settings = profile->GetHostContentSettingsMap();
  ContentSettingsPattern pattern(ContentSettingsPattern::FromURL(origin_url));
  if (!settings || !pattern.IsValid())
    return;

  scoped_ptr<base::Value> value(
      settings->GetWebsiteSetting(origin_url,
                                  origin_url,
                                  CONTENT_SETTINGS_TYPE_APP_BANNER,
                                  std::string(),
                                  NULL));
  base::DictionaryValue* banner_dict = NULL;
  if (value.get() && value->IsType(base::Value::TYPE_DICTIONARY)) {
    banner_dict = static_cast<base::DictionaryValue*>(value.release());
  } else {
    banner_dict = new base::DictionaryValue();
  }

  // Update the setting and save it back.
  banner_dict->SetBoolean(sanitized_package_name, false);
  settings->SetWebsiteSetting(pattern,
                              ContentSettingsPattern::Wildcard(),
                              CONTENT_SETTINGS_TYPE_APP_BANNER,
                              std::string(),
                              banner_dict);
}
<|endoftext|>


<commit_before>#include <TelepathyQt4/Connection>
#include <TelepathyQt4/Contact>
#include <TelepathyQt4/ContactManager>
#include <TelepathyQt4/PendingContacts>
#include <TelepathyQt4/PendingReady>

#include <telepathy-glib/telepathy-glib.h>

#include <tests/lib/glib/contacts-conn.h>
#include <tests/lib/test.h>

using namespace Tp;

class TestContactsInfo : public Test
{
    Q_OBJECT

public:
    TestContactsInfo(QObject *parent = 0)
        : Test(parent), mConnService(0)
    { }

protected Q_SLOTS:
    void expectConnInvalidated();
    void expectPendingContactsFinished(Tp::PendingOperation *);
    void onContactInfoChanged(const Tp::ContactInfoFieldList &);

private Q_SLOTS:
    void initTestCase();
    void init();

    void testInfo();

    void cleanup();
    void cleanupTestCase();

private:
    QString mConnName, mConnPath;
    ContactsConnection *mConnService;
    ConnectionPtr mConn;
    QList<ContactPtr> mContacts;
    int mContactsInfoUpdated;
};

void TestContactsInfo::expectConnInvalidated()
{
    mLoop->exit(0);
}

void TestContactsInfo::expectPendingContactsFinished(PendingOperation *op)
{
    if (!op->isFinished()) {
        qWarning() << "unfinished";
        mLoop->exit(1);
        return;
    }

    if (op->isError()) {
        qWarning().nospace() << op->errorName()
            << ": " << op->errorMessage();
        mLoop->exit(2);
        return;
    }

    if (!op->isValid()) {
        qWarning() << "inconsistent results";
        mLoop->exit(3);
        return;
    }

    qDebug() << "finished";
    PendingContacts *pending = qobject_cast<PendingContacts *>(op);
    mContacts = pending->contacts();

    mLoop->exit(0);
}

void TestContactsInfo::onContactInfoChanged(const Tp::ContactInfoFieldList &info)
{
    Q_UNUSED(info);
    mContactsInfoUpdated++;
    mLoop->exit(0);
}

void TestContactsInfo::initTestCase()
{
    initTestCaseImpl();

    g_type_init();
    g_set_prgname("contacts-info");
    tp_debug_set_flags("all");
    dbus_g_bus_get(DBUS_BUS_STARTER, 0);

    gchar *name;
    gchar *connPath;
    GError *error = 0;

    mConnService = CONTACTS_CONNECTION(g_object_new(
            CONTACTS_TYPE_CONNECTION,
            "account", "me@example.com",
            "protocol", "foo",
            0));
    QVERIFY(mConnService != 0);
    QVERIFY(tp_base_connection_register(TP_BASE_CONNECTION(mConnService),
                "foo", &name, &connPath, &error));
    QVERIFY(error == 0);

    QVERIFY(name != 0);
    QVERIFY(connPath != 0);

    mConnName = QLatin1String(name);
    mConnPath = QLatin1String(connPath);

    g_free(name);
    g_free(connPath);

    mConn = Connection::create(mConnName, mConnPath);
    QCOMPARE(mConn->isReady(), false);

    QVERIFY(connect(mConn->requestConnect(),
                    SIGNAL(finished(Tp::PendingOperation*)),
                    SLOT(expectSuccessfulCall(Tp::PendingOperation*))));
    QCOMPARE(mLoop->exec(), 0);
    QCOMPARE(mConn->isReady(), true);

    QCOMPARE(mConn->status(), Connection::StatusConnected);

    QVERIFY(mConn->contactManager()->supportedFeatures().contains(Contact::FeatureInfo));
}

void TestContactsInfo::init()
{
    initImpl();
    mContactsInfoUpdated = 0;
}

void TestContactsInfo::testInfo()
{
    QStringList validIDs = QStringList() << QLatin1String("foo")
        << QLatin1String("bar");

    PendingContacts *pending = mConn->contactManager()->contactsForIdentifiers(
            validIDs, QSet<Contact::Feature>() << Contact::FeatureInfo);
    QVERIFY(connect(pending,
                    SIGNAL(finished(Tp::PendingOperation*)),
                    SLOT(expectPendingContactsFinished(Tp::PendingOperation*))));
    QCOMPARE(mLoop->exec(), 0);

    for (int i = 0; i < mContacts.size(); i++) {
        ContactPtr contact = mContacts[i];

        QCOMPARE(contact->requestedFeatures(),
                 QSet<Contact::Feature>() << Contact::FeatureInfo);
        QCOMPARE(contact->actualFeatures(),
                 QSet<Contact::Feature>() << Contact::FeatureInfo);

        QVERIFY(contact->info().isEmpty());

        connect(contact.data(),
                SIGNAL(infoChanged(const Tp::ContactInfoFieldList &)),
                SLOT(onContactInfoChanged(const Tp::ContactInfoFieldList &)));
    }

    GPtrArray *info_1 = (GPtrArray *) dbus_g_type_specialized_construct (
              TP_ARRAY_TYPE_CONTACT_INFO_FIELD_LIST);
    {
        const gchar * const field_values[2] = {
            "Foo", NULL
        };
        g_ptr_array_add (info_1, tp_value_array_build (3,
                    G_TYPE_STRING, "n",
                    G_TYPE_STRV, NULL,
                    G_TYPE_STRV, field_values,
                    G_TYPE_INVALID));
    }
    GPtrArray *info_2 = (GPtrArray *) dbus_g_type_specialized_construct (
              TP_ARRAY_TYPE_CONTACT_INFO_FIELD_LIST);
    {
        const gchar * const field_values[2] = {
            "Bar", NULL
        };
        g_ptr_array_add (info_2, tp_value_array_build (3,
                    G_TYPE_STRING, "n",
                    G_TYPE_STRV, NULL,
                    G_TYPE_STRV, field_values,
                    G_TYPE_INVALID));
    }
    GPtrArray *infos[] = { info_1, info_2 };

    TpHandle handles[] = { 0, 0 };
    TpHandleRepoIface *serviceRepo = tp_base_connection_get_handles(
            (TpBaseConnection *) mConnService, TP_HANDLE_TYPE_CONTACT);

    for (unsigned i = 0; i < 2; i++) {
        handles[i] = tp_handle_ensure(serviceRepo, qPrintable(validIDs[i]),
                NULL, NULL);
    }

    contacts_connection_change_infos(mConnService, 2, handles, infos);

    while (mContactsInfoUpdated != 2)  {
        QCOMPARE(mLoop->exec(), 0);
    }

    mContactsInfoUpdated = 0;
    ContactPtr contactFoo = mContacts[0];
    ContactPtr contactBar = mContacts[1];

    QCOMPARE(contactFoo->info().size(), 1);
    QCOMPARE(contactFoo->info()[0].fieldName, QLatin1String("n"));
    QCOMPARE(contactFoo->info()[0].fieldValue[0], QLatin1String("Foo"));
    QCOMPARE(contactBar->info().size(), 1);
    QCOMPARE(contactBar->info()[0].fieldName, QLatin1String("n"));
    QCOMPARE(contactBar->info()[0].fieldValue[0], QLatin1String("Bar"));

    foreach (const ContactPtr &contact, mContacts) {
        PendingOperation *op = contact->refreshInfo();
        QVERIFY(connect(op,
                    SIGNAL(finished(Tp::PendingOperation*)),
                    SLOT(expectSuccessfulCall(Tp::PendingOperation*))));
        QCOMPARE(mLoop->exec(), 0);
    }

    while (mContactsInfoUpdated != 2)  {
        QCOMPARE(mLoop->exec(), 0);
    }

    QCOMPARE(contactFoo->info().size(), 2);
    QCOMPARE(contactFoo->info()[0].fieldName, QLatin1String("n"));
    QCOMPARE(contactFoo->info()[0].fieldValue[0], QLatin1String("Foo"));
    QCOMPARE(contactFoo->info()[1].fieldName, QLatin1String("url"));
    QCOMPARE(contactFoo->info()[1].fieldValue[0], QLatin1String("http://telepathy.freedesktop.org"));
    QCOMPARE(contactBar->info().size(), 2);
    QCOMPARE(contactBar->info()[0].fieldName, QLatin1String("n"));
    QCOMPARE(contactBar->info()[0].fieldValue[0], QLatin1String("Bar"));
    QCOMPARE(contactBar->info()[1].fieldName, QLatin1String("url"));
    QCOMPARE(contactBar->info()[1].fieldValue[0], QLatin1String("http://telepathy.freedesktop.org"));

    g_boxed_free (TP_ARRAY_TYPE_CONTACT_INFO_FIELD_LIST, info_1);
    g_boxed_free (TP_ARRAY_TYPE_CONTACT_INFO_FIELD_LIST, info_2);
}

void TestContactsInfo::cleanup()
{
    cleanupImpl();
}

void TestContactsInfo::cleanupTestCase()
{
    if (mConn) {
        // Disconnect and wait for invalidated
        QVERIFY(connect(mConn->requestDisconnect(),
                        SIGNAL(finished(Tp::PendingOperation*)),
                        SLOT(expectSuccessfulCall(Tp::PendingOperation*))));
        QCOMPARE(mLoop->exec(), 0);

        if (mConn->isValid()) {
            QVERIFY(connect(mConn.data(),
                            SIGNAL(invalidated(Tp::DBusProxy *,
                                               const QString &, const QString &)),
                            SLOT(expectConnInvalidated())));
            QCOMPARE(mLoop->exec(), 0);
        }
    }

    if (mConnService != 0) {
        g_object_unref(mConnService);
        mConnService = 0;
    }

    cleanupTestCaseImpl();
}

QTEST_MAIN(TestContactsInfo)
#include "_gen/contacts-info.cpp.moc.hpp"
<commit_msg>contacts-info test: Added test for Tp::Contact::requestInfo().<commit_after>#include <TelepathyQt4/Connection>
#include <TelepathyQt4/Contact>
#include <TelepathyQt4/ContactManager>
#include <TelepathyQt4/PendingContacts>
#include <TelepathyQt4/PendingContactInfo>
#include <TelepathyQt4/PendingReady>

#include <telepathy-glib/telepathy-glib.h>

#include <tests/lib/glib/contacts-conn.h>
#include <tests/lib/test.h>

using namespace Tp;

class TestContactsInfo : public Test
{
    Q_OBJECT

public:
    TestContactsInfo(QObject *parent = 0)
        : Test(parent), mConnService(0)
    { }

protected Q_SLOTS:
    void expectConnInvalidated();
    void expectPendingContactsFinished(Tp::PendingOperation *);
    void onContactInfoChanged(const Tp::ContactInfoFieldList &);

private Q_SLOTS:
    void initTestCase();
    void init();

    void testInfo();

    void cleanup();
    void cleanupTestCase();

private:
    QString mConnName, mConnPath;
    ContactsConnection *mConnService;
    ConnectionPtr mConn;
    QList<ContactPtr> mContacts;
    int mContactsInfoUpdated;
};

void TestContactsInfo::expectConnInvalidated()
{
    mLoop->exit(0);
}

void TestContactsInfo::expectPendingContactsFinished(PendingOperation *op)
{
    if (!op->isFinished()) {
        qWarning() << "unfinished";
        mLoop->exit(1);
        return;
    }

    if (op->isError()) {
        qWarning().nospace() << op->errorName()
            << ": " << op->errorMessage();
        mLoop->exit(2);
        return;
    }

    if (!op->isValid()) {
        qWarning() << "inconsistent results";
        mLoop->exit(3);
        return;
    }

    qDebug() << "finished";
    PendingContacts *pending = qobject_cast<PendingContacts *>(op);
    mContacts = pending->contacts();

    mLoop->exit(0);
}

void TestContactsInfo::onContactInfoChanged(const Tp::ContactInfoFieldList &info)
{
    Q_UNUSED(info);
    mContactsInfoUpdated++;
    mLoop->exit(0);
}

void TestContactsInfo::initTestCase()
{
    initTestCaseImpl();

    g_type_init();
    g_set_prgname("contacts-info");
    tp_debug_set_flags("all");
    dbus_g_bus_get(DBUS_BUS_STARTER, 0);

    gchar *name;
    gchar *connPath;
    GError *error = 0;

    mConnService = CONTACTS_CONNECTION(g_object_new(
            CONTACTS_TYPE_CONNECTION,
            "account", "me@example.com",
            "protocol", "foo",
            0));
    QVERIFY(mConnService != 0);
    QVERIFY(tp_base_connection_register(TP_BASE_CONNECTION(mConnService),
                "foo", &name, &connPath, &error));
    QVERIFY(error == 0);

    QVERIFY(name != 0);
    QVERIFY(connPath != 0);

    mConnName = QLatin1String(name);
    mConnPath = QLatin1String(connPath);

    g_free(name);
    g_free(connPath);

    mConn = Connection::create(mConnName, mConnPath);
    QCOMPARE(mConn->isReady(), false);

    QVERIFY(connect(mConn->requestConnect(),
                    SIGNAL(finished(Tp::PendingOperation*)),
                    SLOT(expectSuccessfulCall(Tp::PendingOperation*))));
    QCOMPARE(mLoop->exec(), 0);
    QCOMPARE(mConn->isReady(), true);

    QCOMPARE(mConn->status(), Connection::StatusConnected);

    QVERIFY(mConn->contactManager()->supportedFeatures().contains(Contact::FeatureInfo));
}

void TestContactsInfo::init()
{
    initImpl();
    mContactsInfoUpdated = 0;
}

void TestContactsInfo::testInfo()
{
    QStringList validIDs = QStringList() << QLatin1String("foo")
        << QLatin1String("bar");

    PendingContacts *pending = mConn->contactManager()->contactsForIdentifiers(
            validIDs, QSet<Contact::Feature>() << Contact::FeatureInfo);
    QVERIFY(connect(pending,
                    SIGNAL(finished(Tp::PendingOperation*)),
                    SLOT(expectPendingContactsFinished(Tp::PendingOperation*))));
    QCOMPARE(mLoop->exec(), 0);

    for (int i = 0; i < mContacts.size(); i++) {
        ContactPtr contact = mContacts[i];

        QCOMPARE(contact->requestedFeatures(),
                 QSet<Contact::Feature>() << Contact::FeatureInfo);
        QCOMPARE(contact->actualFeatures(),
                 QSet<Contact::Feature>() << Contact::FeatureInfo);

        QVERIFY(contact->info().isEmpty());

        connect(contact.data(),
                SIGNAL(infoChanged(const Tp::ContactInfoFieldList &)),
                SLOT(onContactInfoChanged(const Tp::ContactInfoFieldList &)));
    }

    GPtrArray *info_1 = (GPtrArray *) dbus_g_type_specialized_construct (
              TP_ARRAY_TYPE_CONTACT_INFO_FIELD_LIST);
    {
        const gchar * const field_values[2] = {
            "Foo", NULL
        };
        g_ptr_array_add (info_1, tp_value_array_build (3,
                    G_TYPE_STRING, "n",
                    G_TYPE_STRV, NULL,
                    G_TYPE_STRV, field_values,
                    G_TYPE_INVALID));
    }
    GPtrArray *info_2 = (GPtrArray *) dbus_g_type_specialized_construct (
              TP_ARRAY_TYPE_CONTACT_INFO_FIELD_LIST);
    {
        const gchar * const field_values[2] = {
            "Bar", NULL
        };
        g_ptr_array_add (info_2, tp_value_array_build (3,
                    G_TYPE_STRING, "n",
                    G_TYPE_STRV, NULL,
                    G_TYPE_STRV, field_values,
                    G_TYPE_INVALID));
    }
    GPtrArray *infos[] = { info_1, info_2 };

    TpHandle handles[] = { 0, 0 };
    TpHandleRepoIface *serviceRepo = tp_base_connection_get_handles(
            (TpBaseConnection *) mConnService, TP_HANDLE_TYPE_CONTACT);

    for (unsigned i = 0; i < 2; i++) {
        handles[i] = tp_handle_ensure(serviceRepo, qPrintable(validIDs[i]),
                NULL, NULL);
    }

    contacts_connection_change_infos(mConnService, 2, handles, infos);

    while (mContactsInfoUpdated != 2)  {
        QCOMPARE(mLoop->exec(), 0);
    }

    mContactsInfoUpdated = 0;
    ContactPtr contactFoo = mContacts[0];
    ContactPtr contactBar = mContacts[1];

    QCOMPARE(contactFoo->info().size(), 1);
    QCOMPARE(contactFoo->info()[0].fieldName, QLatin1String("n"));
    QCOMPARE(contactFoo->info()[0].fieldValue[0], QLatin1String("Foo"));
    QCOMPARE(contactBar->info().size(), 1);
    QCOMPARE(contactBar->info()[0].fieldName, QLatin1String("n"));
    QCOMPARE(contactBar->info()[0].fieldValue[0], QLatin1String("Bar"));

    foreach (const ContactPtr &contact, mContacts) {
        PendingOperation *op = contact->refreshInfo();
        QVERIFY(connect(op,
                    SIGNAL(finished(Tp::PendingOperation*)),
                    SLOT(expectSuccessfulCall(Tp::PendingOperation*))));
        QCOMPARE(mLoop->exec(), 0);
    }

    while (mContactsInfoUpdated != 2)  {
        QCOMPARE(mLoop->exec(), 0);
    }

    QCOMPARE(contactFoo->info().size(), 2);
    QCOMPARE(contactFoo->info()[0].fieldName, QLatin1String("n"));
    QCOMPARE(contactFoo->info()[0].fieldValue[0], QLatin1String("Foo"));
    QCOMPARE(contactFoo->info()[1].fieldName, QLatin1String("url"));
    QCOMPARE(contactFoo->info()[1].fieldValue[0], QLatin1String("http://telepathy.freedesktop.org"));
    QCOMPARE(contactBar->info().size(), 2);
    QCOMPARE(contactBar->info()[0].fieldName, QLatin1String("n"));
    QCOMPARE(contactBar->info()[0].fieldValue[0], QLatin1String("Bar"));
    QCOMPARE(contactBar->info()[1].fieldName, QLatin1String("url"));
    QCOMPARE(contactBar->info()[1].fieldValue[0], QLatin1String("http://telepathy.freedesktop.org"));

    for (int i = 0; i < mContacts.size(); i++) {
        ContactPtr contact = mContacts[i];
        disconnect(contact.data(),
                SIGNAL(infoChanged(const Tp::ContactInfoFieldList &)),
                this,
                SLOT(onContactInfoChanged(const Tp::ContactInfoFieldList &)));
    }

    PendingContactInfo *pci = contactFoo->requestInfo();
    QVERIFY(connect(pci,
                SIGNAL(finished(Tp::PendingOperation*)),
                SLOT(expectSuccessfulCall(Tp::PendingOperation*))));
    while (!pci->isFinished()) {
        QCOMPARE(mLoop->exec(), 0);
    }

    QCOMPARE(pci->info().size(), 2);
    QCOMPARE(pci->info()[0].fieldName, QLatin1String("n"));
    QCOMPARE(pci->info()[0].fieldValue[0], QLatin1String("Foo"));
    QCOMPARE(pci->info()[1].fieldName, QLatin1String("url"));
    QCOMPARE(pci->info()[1].fieldValue[0], QLatin1String("http://telepathy.freedesktop.org"));

    g_boxed_free (TP_ARRAY_TYPE_CONTACT_INFO_FIELD_LIST, info_1);
    g_boxed_free (TP_ARRAY_TYPE_CONTACT_INFO_FIELD_LIST, info_2);
}

void TestContactsInfo::cleanup()
{
    cleanupImpl();
}

void TestContactsInfo::cleanupTestCase()
{
    if (mConn) {
        // Disconnect and wait for invalidated
        QVERIFY(connect(mConn->requestDisconnect(),
                        SIGNAL(finished(Tp::PendingOperation*)),
                        SLOT(expectSuccessfulCall(Tp::PendingOperation*))));
        QCOMPARE(mLoop->exec(), 0);

        if (mConn->isValid()) {
            QVERIFY(connect(mConn.data(),
                            SIGNAL(invalidated(Tp::DBusProxy *,
                                               const QString &, const QString &)),
                            SLOT(expectConnInvalidated())));
            QCOMPARE(mLoop->exec(), 0);
        }
    }

    if (mConnService != 0) {
        g_object_unref(mConnService);
        mConnService = 0;
    }

    cleanupTestCaseImpl();
}

QTEST_MAIN(TestContactsInfo)
#include "_gen/contacts-info.cpp.moc.hpp"
<|endoftext|>


<commit_before>#include "LogSinks.hpp"
#include "macros.hpp"
#include <unistd.h>
#include <iostream>
#include <ctime>
#include <sstream>

static const char* const ESCAPE_BOLD = "\x1B[1m";
static const char* const ESCAPE_NORMALFONT = "\x1B[0m";
static const char* const ESCAPE_BLACK_FOREGROUND = "\x1B[30m";
static const char* const ESCAPE_RED_FOREGROUND = "\x1B[31m";
static const char* const ESCAPE_GREEN_FOREGROUND = "\x1B[32m";
static const char* const ESCAPE_YELLOW_FOREGROUND = "\x1B[33m";
static const char* const ESCAPE_BLUE_FOREGROUND = "\x1B[34m";
static const char* const ESCAPE_MAGENTA_FOREGROUND = "\x1B[35m";
static const char* const ESCAPE_CYAN_FOREGROUND = "\x1B[36m";
static const char* const ESCAPE_WHITE_FOREGROUND = "\x1B[37m";

static void HOT printDateTime(uint64_t timestamp, std::ostream& stream) {
    //Convert timestamp to timeval
    struct timeval tv;
    tv.tv_sec = timestamp / 1000;
    tv.tv_usec = (timestamp % 1000) * 1000;
    //Format the tm data
    char dateBuffer[32];
    size_t formattedLength = strftime(dateBuffer, 32, "%F %T", localtime(&(tv.tv_sec)));
    assert(formattedLength > 0);
    //Format the subsecond part
    snprintf(dateBuffer + formattedLength, 32 - formattedLength, ".%03lu", (unsigned long) (tv.tv_usec / 1000));
    stream << '[' << dateBuffer << ']';
}

std::string logLevelToString(LogLevel logLevel) {
    switch (logLevel) {
        case LogLevel::Critical: {
            return "Critical";
        }
        case LogLevel::Error: {
            return "Error";
        }
        case LogLevel::Warn: {
            return "Warn";
        }
        case LogLevel::Info: {
            return "Info";
        }
        case LogLevel::Debug: {
            return "Debug";
        }
        case LogLevel::Trace: {
            return "Trace";
        }
        default: {
            return "Unknown";
        }
    }
}

LogSink::~LogSink() {

}

StderrLogSink::StderrLogSink() : coloredLogging(isatty(fileno(stderr))) {

}

void StderrLogSink::setColoredLogging(bool value) {
    this->coloredLogging = value;
}

void HOT StderrLogSink::log(LogLevel logLevel, uint64_t timestamp, const std::string& senderName, const std::string& logMessage) {

    switch (logLevel) {
        case LogLevel::Critical: {
            if(coloredLogging) {
                std::cerr << ESCAPE_BOLD << ESCAPE_RED_FOREGROUND;
            }
            printDateTime(timestamp, std::cerr);
            std::cerr << "[Error] " << senderName << " - " << logMessage;
            if(coloredLogging) {
                std::cerr << ESCAPE_NORMALFONT << ESCAPE_BLACK_FOREGROUND;
            }
            std::cerr << std::endl;
            break;
        }
        case LogLevel::Error: {
            if(coloredLogging) {
                std::cerr << ESCAPE_RED_FOREGROUND;
            }
            printDateTime(timestamp, std::cerr);
            std::cerr << "[Error] " << senderName << " - ";
            if(coloredLogging) {
                std::cerr <<  ESCAPE_BLACK_FOREGROUND << std::endl;
            }
            std::cerr << logMessage << std::endl;
            break;
        }
        case LogLevel::Warn: {
            if(coloredLogging) {
                std::cerr << ESCAPE_YELLOW_FOREGROUND;
            }
            printDateTime(timestamp, std::cerr);
            std::cerr << "[Warning] " << senderName << " - ";
            if(coloredLogging) {
                std::cerr << ESCAPE_BLACK_FOREGROUND;
            }
            std::cerr << logMessage << std::endl;
            break;
        }
        case LogLevel::Info: {
            if(coloredLogging) {
                std::cerr << ESCAPE_GREEN_FOREGROUND;
            }
            printDateTime(timestamp, std::cerr);
            std::cerr << "[Info] " << senderName << " - ";
            if(coloredLogging) {
                std::cerr << ESCAPE_BLACK_FOREGROUND;
            }
            std::cerr << logMessage << std::endl;
            break;
        }
        case LogLevel::Debug: {
            if(coloredLogging) {
                std::cerr << ESCAPE_BLUE_FOREGROUND;
            }
            printDateTime(timestamp, std::cerr);
            std::cerr << "[Debug] " << senderName << " - ";
            if(coloredLogging) {
                std::cerr << ESCAPE_BLACK_FOREGROUND;
            }
            std::cerr << logMessage << std::endl;
            break;
        }
        case LogLevel::Trace: {
            if(coloredLogging) {
                std::cerr << ESCAPE_CYAN_FOREGROUND;
            }
            printDateTime(timestamp, std::cerr);
            std::cerr << "[Trace] " << senderName << " - ";
            if(coloredLogging) {
                std::cerr << ESCAPE_BLACK_FOREGROUND;
            }
            std::cerr << logMessage << std::endl;
            break;
        }
        default: {
            printDateTime(timestamp, std::cerr);
            std::cerr << "[Unknown] " << senderName << " - " << logMessage << std::endl;
            break;
        }
    }
}

FileLogSink::FileLogSink(const std::string& filename) : fout(filename.c_str()), filename(filename) {
}

FileLogSink::~FileLogSink() {
    fout.close();
}

void FileLogSink::log(LogLevel logLevel, uint64_t timestamp, const std::string& senderName, const std::string& logMessage) {
    printDateTime(timestamp, fout);
    //Not flushing (endl) would be faster, but log msgs before a crash might be lost
    fout << " [" << logLevelToString(logLevel) << "] " << senderName << " - " << logMessage << std::endl;
}

BufferLogSink::LogMessage::LogMessage(LogLevel level, uint64_t timestamp, const std::string& message, const std::string& sender) : level(level), timestamp(timestamp), message(message), sender(sender) {
}

BufferLogSink::BufferLogSink(size_t maxBufferSize) : maxBufferSize(maxBufferSize), bufferMutex() {

}

BufferLogSink::~BufferLogSink() {

}

std::deque<BufferLogSink::LogMessage>& BufferLogSink::getLogMessages() {
    bufferMutex.lock();
    return buffer;
}

void BufferLogSink::unlock() {
    bufferMutex.unlock();
}

void BufferLogSink::log(LogLevel logLevel, uint64_t timestamp, const std::string& senderName, const std::string& logMessage) {
    //Create the entry
    bufferMutex.lock();
    buffer.emplace_front(logLevel, timestamp, logMessage, senderName);
    //Expunge the first msgs if buffer is full
    if(buffer.size() > maxBufferSize) {
        buffer.pop_back();
    }
    bufferMutex.unlock();
}<commit_msg>Reversed logging order<commit_after>#include "LogSinks.hpp"
#include "macros.hpp"
#include <unistd.h>
#include <iostream>
#include <ctime>
#include <sstream>

static const char* const ESCAPE_BOLD = "\x1B[1m";
static const char* const ESCAPE_NORMALFONT = "\x1B[0m";
static const char* const ESCAPE_BLACK_FOREGROUND = "\x1B[30m";
static const char* const ESCAPE_RED_FOREGROUND = "\x1B[31m";
static const char* const ESCAPE_GREEN_FOREGROUND = "\x1B[32m";
static const char* const ESCAPE_YELLOW_FOREGROUND = "\x1B[33m";
static const char* const ESCAPE_BLUE_FOREGROUND = "\x1B[34m";
static const char* const ESCAPE_MAGENTA_FOREGROUND = "\x1B[35m";
static const char* const ESCAPE_CYAN_FOREGROUND = "\x1B[36m";
static const char* const ESCAPE_WHITE_FOREGROUND = "\x1B[37m";

static void HOT printDateTime(uint64_t timestamp, std::ostream& stream) {
    //Convert timestamp to timeval
    struct timeval tv;
    tv.tv_sec = timestamp / 1000;
    tv.tv_usec = (timestamp % 1000) * 1000;
    //Format the tm data
    char dateBuffer[32];
    size_t formattedLength = strftime(dateBuffer, 32, "%F %T", localtime(&(tv.tv_sec)));
    assert(formattedLength > 0);
    //Format the subsecond part
    snprintf(dateBuffer + formattedLength, 32 - formattedLength, ".%03lu", (unsigned long) (tv.tv_usec / 1000));
    stream << '[' << dateBuffer << ']';
}

std::string logLevelToString(LogLevel logLevel) {
    switch (logLevel) {
        case LogLevel::Critical: {
            return "Critical";
        }
        case LogLevel::Error: {
            return "Error";
        }
        case LogLevel::Warn: {
            return "Warn";
        }
        case LogLevel::Info: {
            return "Info";
        }
        case LogLevel::Debug: {
            return "Debug";
        }
        case LogLevel::Trace: {
            return "Trace";
        }
        default: {
            return "Unknown";
        }
    }
}

LogSink::~LogSink() {

}

StderrLogSink::StderrLogSink() : coloredLogging(isatty(fileno(stderr))) {

}

void StderrLogSink::setColoredLogging(bool value) {
    this->coloredLogging = value;
}

void HOT StderrLogSink::log(LogLevel logLevel, uint64_t timestamp, const std::string& senderName, const std::string& logMessage) {

    switch (logLevel) {
        case LogLevel::Critical: {
            if(coloredLogging) {
                std::cerr << ESCAPE_BOLD << ESCAPE_RED_FOREGROUND;
            }
            printDateTime(timestamp, std::cerr);
            std::cerr << "[Error] " << senderName << " - " << logMessage;
            if(coloredLogging) {
                std::cerr << ESCAPE_NORMALFONT << ESCAPE_BLACK_FOREGROUND;
            }
            std::cerr << std::endl;
            break;
        }
        case LogLevel::Error: {
            if(coloredLogging) {
                std::cerr << ESCAPE_RED_FOREGROUND;
            }
            printDateTime(timestamp, std::cerr);
            std::cerr << "[Error] " << senderName << " - ";
            if(coloredLogging) {
                std::cerr <<  ESCAPE_BLACK_FOREGROUND << std::endl;
            }
            std::cerr << logMessage << std::endl;
            break;
        }
        case LogLevel::Warn: {
            if(coloredLogging) {
                std::cerr << ESCAPE_YELLOW_FOREGROUND;
            }
            printDateTime(timestamp, std::cerr);
            std::cerr << "[Warning] " << senderName << " - ";
            if(coloredLogging) {
                std::cerr << ESCAPE_BLACK_FOREGROUND;
            }
            std::cerr << logMessage << std::endl;
            break;
        }
        case LogLevel::Info: {
            if(coloredLogging) {
                std::cerr << ESCAPE_GREEN_FOREGROUND;
            }
            printDateTime(timestamp, std::cerr);
            std::cerr << "[Info] " << senderName << " - ";
            if(coloredLogging) {
                std::cerr << ESCAPE_BLACK_FOREGROUND;
            }
            std::cerr << logMessage << std::endl;
            break;
        }
        case LogLevel::Debug: {
            if(coloredLogging) {
                std::cerr << ESCAPE_BLUE_FOREGROUND;
            }
            printDateTime(timestamp, std::cerr);
            std::cerr << "[Debug] " << senderName << " - ";
            if(coloredLogging) {
                std::cerr << ESCAPE_BLACK_FOREGROUND;
            }
            std::cerr << logMessage << std::endl;
            break;
        }
        case LogLevel::Trace: {
            if(coloredLogging) {
                std::cerr << ESCAPE_CYAN_FOREGROUND;
            }
            printDateTime(timestamp, std::cerr);
            std::cerr << "[Trace] " << senderName << " - ";
            if(coloredLogging) {
                std::cerr << ESCAPE_BLACK_FOREGROUND;
            }
            std::cerr << logMessage << std::endl;
            break;
        }
        default: {
            printDateTime(timestamp, std::cerr);
            std::cerr << "[Unknown] " << senderName << " - " << logMessage << std::endl;
            break;
        }
    }
}

FileLogSink::FileLogSink(const std::string& filename) : fout(filename.c_str()), filename(filename) {
}

FileLogSink::~FileLogSink() {
    fout.close();
}

void FileLogSink::log(LogLevel logLevel, uint64_t timestamp, const std::string& senderName, const std::string& logMessage) {
    printDateTime(timestamp, fout);
    //Not flushing (endl) would be faster, but log msgs before a crash might be lost
    fout << " [" << logLevelToString(logLevel) << "] " << senderName << " - " << logMessage << std::endl;
}

BufferLogSink::LogMessage::LogMessage(LogLevel level, uint64_t timestamp, const std::string& message, const std::string& sender) : level(level), timestamp(timestamp), message(message), sender(sender) {
}

BufferLogSink::BufferLogSink(size_t maxBufferSize) : maxBufferSize(maxBufferSize), bufferMutex() {

}

BufferLogSink::~BufferLogSink() {

}

std::deque<BufferLogSink::LogMessage>& BufferLogSink::getLogMessages() {
    bufferMutex.lock();
    return buffer;
}

void BufferLogSink::unlock() {
    bufferMutex.unlock();
}

void BufferLogSink::log(LogLevel logLevel, uint64_t timestamp, const std::string& senderName, const std::string& logMessage) {
    //Create the entry
    bufferMutex.lock();
    buffer.emplace_back(logLevel, timestamp, logMessage, senderName);
    //Expunge the first msgs if buffer is full
    if(buffer.size() > maxBufferSize) {
        buffer.pop_front();
    }
    bufferMutex.unlock();
}<|endoftext|>


<commit_before>
int GetFontHeight(void *TheFont)
{
   //MSG("GetFontHeight()");
   return static_cast<objFont *>(TheFont)->MaxHeight;
}

int GetFontLeading(void *TheFont)
{
   //MSG("GetFontLeading()");
   return static_cast<objFont *>(TheFont)->Leading;
}

int GetFontGutter(void *TheFont)
{
   //MSG("GetFontGutter()");
   return static_cast<objFont *>(TheFont)->Gutter;
}

/*****************************************************************************
** Point class
*/

Scintilla::Point Scintilla::Point::FromLong(long lpoint)
{
   return Scintilla::Point(Scintilla::Platform::LowShortFromLong(lpoint),
      Scintilla::Platform::HighShortFromLong(lpoint));
}

/*****************************************************************************
** Palette class.  Functionality not required as we only use 32 bit colours.
*/

Scintilla::Palette::Palette() { }
Scintilla::Palette::~Palette() { }
void Scintilla::Palette::Release() { }
void Scintilla::Palette::Allocate(Scintilla::Window &w) { }

void Scintilla::Palette::WantFind(Scintilla::ColourPair &cp, bool want)
{
   cp.allocated.Set(cp.desired.AsLong());
}

/*****************************************************************************
** Font class
**
** Not really supported as we only need to allocate 3 main fonts in the
** Scintilla class to serve all of our font needs in an edited document.
** Scintilla will try to create a font for every style allocated, which is
** overkill.
*/

Scintilla::Font::Font()
{
   bold = 0;
   italic = 0;
}

Scintilla::Font::~Font()
{

}

void Scintilla::Font::Create(const char *faceName, int characterSet, int size, bool bold_, bool italic_, int)
{
   bold = bold_;
   italic = italic_;

   FMSG("Font::Create:","Face: %s, Style:%s%s", faceName, (bold) ? " Bold" : "", (italic) ? " Italic" : "");
}

void Scintilla::Font::Release()
{
}

/*****************************************************************************
** BitmapClipper class
**
** Utility class used by SurfacePan
*/

class BitmapClipper
{
public:
   BitmapClipper(struct rkBitmap *bitmap_, const Scintilla::PRectangle& cliprect) :  bitmap(bitmap_)
   {
      /*** Save old clipping rectangle ***/

      saved_cliprect.left = bitmap->Clip.Left;
      saved_cliprect.top = bitmap->Clip.Top;
      saved_cliprect.right = bitmap->Clip.Right;
      saved_cliprect.bottom = bitmap->Clip.Bottom;

      /*** Apply new clipping rectangle ***/

      bitmap->Clip.Left = MAX(bitmap->Clip.Left, cliprect.left);
      bitmap->Clip.Top = MAX(bitmap->Clip.Top, cliprect.top);
      bitmap->Clip.Right = MIN(bitmap->Clip.Right, cliprect.right);
      bitmap->Clip.Bottom = MIN(bitmap->Clip.Bottom, cliprect.bottom);
   }

   ~BitmapClipper()
   {
      /*** Restore old clipping rectangle ***/

      bitmap->Clip.Left = saved_cliprect.left;
      bitmap->Clip.Top = saved_cliprect.top;
      bitmap->Clip.Right = saved_cliprect.right;
      bitmap->Clip.Bottom = saved_cliprect.bottom;
   }

private:
   struct rkBitmap *bitmap;
   Scintilla::PRectangle saved_cliprect;
};

/*****************************************************************************
** DynamicLibraryImpl class
*/

class DynamicLibraryImpl : public Scintilla::DynamicLibrary
{
protected:

public:
   DynamicLibraryImpl(const char *modulePath)
   {
      LogF("DynamicLibraryImpl::DynamicLibraryImpl():","path: %s", modulePath);
   }

   virtual ~DynamicLibraryImpl()
   {

   }

   // Use g_module_symbol to get a pointer to the relevant function.
   virtual void * FindFunction(const char *name)
   {
      LogF("DynamicLibraryImpl::FindFunction():","name: %s", name);
      return NULL;/* TEMP */
   }

   virtual bool IsValid()
   {
      return TRUE;/* TEMP HACK */
   }
};

Scintilla::DynamicLibrary * Scintilla::DynamicLibrary::Load(const char *modulePath)
{
   LogF("DynamicLibraryImpl::Load():","modulePath: %s", modulePath);
   return static_cast<DynamicLibrary *>( new DynamicLibraryImpl(modulePath) );
}

/*****************************************************************************
** ElapsedTime class
*/

Scintilla::ElapsedTime::ElapsedTime()
{
   Duration(TRUE);//reset time
}

double Scintilla::ElapsedTime::Duration(bool reset)
{
   LARGE systime = PreciseTime() / 1000LL;
   LARGE lasttime = ((LARGE)bigBit<<32) + *(ULONG*)&littleBit;
   DOUBLE elapsed = systime - lasttime;

   if (reset) {
      bigBit = (long)(systime>>32);
      *(ULONG*)&littleBit = (systime & 0xFFFFFFFF);
   }

   return elapsed * 0.001;
}

/*****************************************************************************
** Platform class
*/

Scintilla::ColourDesired Scintilla::Platform::Chrome()
{
   return ColourDesired(0xe0, 0xe0, 0xe0);
}

Scintilla::ColourDesired Scintilla::Platform::ChromeHighlight()
{
   return Scintilla::ColourDesired(0xff, 0xff, 0xff);
}

const char * Scintilla::Platform::DefaultFont()
{
   return "Courier";
}

int Scintilla::Platform::DefaultFontSize()
{
   return 20;
}

unsigned int Scintilla::Platform::DoubleClickTime()
{
   return 500; // Half a second
}

bool Scintilla::Platform::MouseButtonBounce()
{
   return true;
}

void Scintilla::Platform::DebugDisplay(const char *string)
{
   LogF("Scintilla:", string);
}

bool Scintilla::Platform::IsKeyDown(int)
{
   LogF("Platform::IsKeyDown","UNSUPPORTED");

   // TODO: discover state of keys in GTK+/X
   return false;
}

long Scintilla::Platform::SendScintilla(Scintilla::WindowID w, unsigned int msg, unsigned long wParam, long lParam)
{
   LogF("Platform::SendScintilla","UNSUPPORTED");
   return 0;
}

long Scintilla::Platform::SendScintillaPointer(Scintilla::WindowID w, unsigned int msg, unsigned long wParam, void *lParam)
{
   LogF("Platform::SendScintillaPointer","UNSUPPORTED");

   //return scintilla_send_message(SCINTILLA(w), msg, wParam,
   //   reinterpret_cast<sptr_t>(lParam));
   return 0;
}

bool Scintilla::Platform::IsDBCSLeadByte(int /* codePage */, char /* ch */)
{
   return false;
}

int Scintilla::Platform::DBCSCharLength(int codePage, const char *s)
{
   return 1;/* TEMP HACK */
   /*if (codePage == 999932) {
      // Experimental and disabled code - change 999932 to 932 above to
      // enable locale avoiding but expensive character length determination.
      // Avoid locale with explicit use of iconv
      Converter convMeasure("UCS-2", CharacterSetID(SC_CHARSET_SHIFTJIS));
      size_t lenChar = MultiByteLenFromIconv(convMeasure, s, strlen(s));
      return lenChar;
   }
   else {
      int bytes = mblen(s, MB_CUR_MAX);
      if (bytes >= 1)
         return bytes;
      else
         return 1;
   }*/
}

int Scintilla::Platform::DBCSCharMaxLength()
{
//   return MB_CUR_MAX;
   //return 2;

   return 1;/* TEMP HACK */
}

// These are utility functions not really tied to a platform

int Scintilla::Platform::Minimum(int a, int b)
{
   if (a < b) return a;
   else return b;
}

int Scintilla::Platform::Maximum(int a, int b)
{
   if (a > b) return a;
   else return b;
}

#ifdef DEBUG
void Scintilla::Platform::DebugPrintf(const char *format, ...)
{
#if 1
   LONG *Array;
   Array = (LONG *)&format;
   LogF("Scintilla:", (BYTE *)Array[0], Array[1], Array[2], Array[3], Array[4], Array[5], Array[6], Array[7], Array[8], Array[9], Array[10], Array[11]);
#else
   char buffer[2000];
   va_list pArguments;
   va_start(pArguments, format);
   vsprintf(buffer, format, pArguments);
   va_end(pArguments);
   LogF("Scintilla:", buffer);
#endif
}
#else
void Scintilla::Platform::DebugPrintf(const char *, ...) {}

#endif

// Not supported for GTK+
static bool assertionPopUps = true;

bool Scintilla::Platform::ShowAssertionPopUps(bool assertionPopUps_) {
   bool ret = assertionPopUps;
   assertionPopUps = assertionPopUps_;
   return ret;
}

void Scintilla::Platform::Assert(const char *c, const char *file, int line)
{
   LogF("@Platform::Assert:","%s, File %s, Line %d", c, file, line);
   SelfDestruct();
}

int Scintilla::Platform::Clamp(int val, int minVal, int maxVal)
{
   if (val > maxVal) val = maxVal;
   if (val < minVal) val = minVal;
   return val;
}

void Platform_Initialise()
{

}

void Platform_Finalise()
{

}
<commit_msg>Fixed log message bug in Scintilla<commit_after>
int GetFontHeight(void *TheFont)
{
   //MSG("GetFontHeight()");
   return static_cast<objFont *>(TheFont)->MaxHeight;
}

int GetFontLeading(void *TheFont)
{
   //MSG("GetFontLeading()");
   return static_cast<objFont *>(TheFont)->Leading;
}

int GetFontGutter(void *TheFont)
{
   //MSG("GetFontGutter()");
   return static_cast<objFont *>(TheFont)->Gutter;
}

/*****************************************************************************
** Point class
*/

Scintilla::Point Scintilla::Point::FromLong(long lpoint)
{
   return Scintilla::Point(Scintilla::Platform::LowShortFromLong(lpoint),
      Scintilla::Platform::HighShortFromLong(lpoint));
}

/*****************************************************************************
** Palette class.  Functionality not required as we only use 32 bit colours.
*/

Scintilla::Palette::Palette() { }
Scintilla::Palette::~Palette() { }
void Scintilla::Palette::Release() { }
void Scintilla::Palette::Allocate(Scintilla::Window &w) { }

void Scintilla::Palette::WantFind(Scintilla::ColourPair &cp, bool want)
{
   cp.allocated.Set(cp.desired.AsLong());
}

/*****************************************************************************
** Font class
**
** Not really supported as we only need to allocate 3 main fonts in the
** Scintilla class to serve all of our font needs in an edited document.
** Scintilla will try to create a font for every style allocated, which is
** overkill.
*/

Scintilla::Font::Font()
{
   bold = 0;
   italic = 0;
}

Scintilla::Font::~Font()
{

}

void Scintilla::Font::Create(const char *faceName, int characterSet, int size, bool bold_, bool italic_, int)
{
   bold = bold_;
   italic = italic_;

   FMSG("Font::Create:","Face: %s, Style:%s%s", faceName, (bold) ? " Bold" : "", (italic) ? " Italic" : "");
}

void Scintilla::Font::Release()
{
}

/*****************************************************************************
** BitmapClipper class
**
** Utility class used by SurfacePan
*/

class BitmapClipper
{
public:
   BitmapClipper(struct rkBitmap *bitmap_, const Scintilla::PRectangle& cliprect) :  bitmap(bitmap_)
   {
      /*** Save old clipping rectangle ***/

      saved_cliprect.left = bitmap->Clip.Left;
      saved_cliprect.top = bitmap->Clip.Top;
      saved_cliprect.right = bitmap->Clip.Right;
      saved_cliprect.bottom = bitmap->Clip.Bottom;

      /*** Apply new clipping rectangle ***/

      bitmap->Clip.Left = MAX(bitmap->Clip.Left, cliprect.left);
      bitmap->Clip.Top = MAX(bitmap->Clip.Top, cliprect.top);
      bitmap->Clip.Right = MIN(bitmap->Clip.Right, cliprect.right);
      bitmap->Clip.Bottom = MIN(bitmap->Clip.Bottom, cliprect.bottom);
   }

   ~BitmapClipper()
   {
      /*** Restore old clipping rectangle ***/

      bitmap->Clip.Left = saved_cliprect.left;
      bitmap->Clip.Top = saved_cliprect.top;
      bitmap->Clip.Right = saved_cliprect.right;
      bitmap->Clip.Bottom = saved_cliprect.bottom;
   }

private:
   struct rkBitmap *bitmap;
   Scintilla::PRectangle saved_cliprect;
};

/*****************************************************************************
** DynamicLibraryImpl class
*/

class DynamicLibraryImpl : public Scintilla::DynamicLibrary
{
protected:

public:
   DynamicLibraryImpl(const char *modulePath)
   {
      LogF("DynamicLibraryImpl::DynamicLibraryImpl():","path: %s", modulePath);
   }

   virtual ~DynamicLibraryImpl()
   {

   }

   // Use g_module_symbol to get a pointer to the relevant function.
   virtual void * FindFunction(const char *name)
   {
      LogF("DynamicLibraryImpl::FindFunction():","name: %s", name);
      return NULL;/* TEMP */
   }

   virtual bool IsValid()
   {
      return TRUE;/* TEMP HACK */
   }
};

Scintilla::DynamicLibrary * Scintilla::DynamicLibrary::Load(const char *modulePath)
{
   LogF("DynamicLibraryImpl::Load():","modulePath: %s", modulePath);
   return static_cast<DynamicLibrary *>( new DynamicLibraryImpl(modulePath) );
}

/*****************************************************************************
** ElapsedTime class
*/

Scintilla::ElapsedTime::ElapsedTime()
{
   Duration(TRUE);//reset time
}

double Scintilla::ElapsedTime::Duration(bool reset)
{
   LARGE systime = PreciseTime() / 1000LL;
   LARGE lasttime = ((LARGE)bigBit<<32) + *(ULONG*)&littleBit;
   DOUBLE elapsed = systime - lasttime;

   if (reset) {
      bigBit = (long)(systime>>32);
      *(ULONG*)&littleBit = (systime & 0xFFFFFFFF);
   }

   return elapsed * 0.001;
}

/*****************************************************************************
** Platform class
*/

Scintilla::ColourDesired Scintilla::Platform::Chrome()
{
   return ColourDesired(0xe0, 0xe0, 0xe0);
}

Scintilla::ColourDesired Scintilla::Platform::ChromeHighlight()
{
   return Scintilla::ColourDesired(0xff, 0xff, 0xff);
}

const char * Scintilla::Platform::DefaultFont()
{
   return "Courier";
}

int Scintilla::Platform::DefaultFontSize()
{
   return 20;
}

unsigned int Scintilla::Platform::DoubleClickTime()
{
   return 500; // Half a second
}

bool Scintilla::Platform::MouseButtonBounce()
{
   return true;
}

void Scintilla::Platform::DebugDisplay(const char *string)
{
   LogF("Scintilla:", "%s", string);
}

bool Scintilla::Platform::IsKeyDown(int)
{
   LogF("Platform::IsKeyDown","UNSUPPORTED");

   // TODO: discover state of keys in GTK+/X
   return false;
}

long Scintilla::Platform::SendScintilla(Scintilla::WindowID w, unsigned int msg, unsigned long wParam, long lParam)
{
   LogF("Platform::SendScintilla","UNSUPPORTED");
   return 0;
}

long Scintilla::Platform::SendScintillaPointer(Scintilla::WindowID w, unsigned int msg, unsigned long wParam, void *lParam)
{
   LogF("Platform::SendScintillaPointer","UNSUPPORTED");

   //return scintilla_send_message(SCINTILLA(w), msg, wParam,
   //   reinterpret_cast<sptr_t>(lParam));
   return 0;
}

bool Scintilla::Platform::IsDBCSLeadByte(int /* codePage */, char /* ch */)
{
   return false;
}

int Scintilla::Platform::DBCSCharLength(int codePage, const char *s)
{
   return 1;/* TEMP HACK */
   /*if (codePage == 999932) {
      // Experimental and disabled code - change 999932 to 932 above to
      // enable locale avoiding but expensive character length determination.
      // Avoid locale with explicit use of iconv
      Converter convMeasure("UCS-2", CharacterSetID(SC_CHARSET_SHIFTJIS));
      size_t lenChar = MultiByteLenFromIconv(convMeasure, s, strlen(s));
      return lenChar;
   }
   else {
      int bytes = mblen(s, MB_CUR_MAX);
      if (bytes >= 1)
         return bytes;
      else
         return 1;
   }*/
}

int Scintilla::Platform::DBCSCharMaxLength()
{
//   return MB_CUR_MAX;
   //return 2;

   return 1;/* TEMP HACK */
}

// These are utility functions not really tied to a platform

int Scintilla::Platform::Minimum(int a, int b)
{
   if (a < b) return a;
   else return b;
}

int Scintilla::Platform::Maximum(int a, int b)
{
   if (a > b) return a;
   else return b;
}

#ifdef DEBUG
void Scintilla::Platform::DebugPrintf(const char *format, ...)
{
#if 1
   LONG *Array;
   Array = (LONG *)&format;
   LogF("Scintilla:", (BYTE *)Array[0], Array[1], Array[2], Array[3], Array[4], Array[5], Array[6], Array[7], Array[8], Array[9], Array[10], Array[11]);
#else
   char buffer[2000];
   va_list pArguments;
   va_start(pArguments, format);
   vsprintf(buffer, format, pArguments);
   va_end(pArguments);
   LogF("Scintilla:", buffer);
#endif
}
#else
void Scintilla::Platform::DebugPrintf(const char *, ...) {}

#endif

// Not supported for GTK+
static bool assertionPopUps = true;

bool Scintilla::Platform::ShowAssertionPopUps(bool assertionPopUps_) {
   bool ret = assertionPopUps;
   assertionPopUps = assertionPopUps_;
   return ret;
}

void Scintilla::Platform::Assert(const char *c, const char *file, int line)
{
   LogF("@Platform::Assert:","%s, File %s, Line %d", c, file, line);
   SelfDestruct();
}

int Scintilla::Platform::Clamp(int val, int minVal, int maxVal)
{
   if (val > maxVal) val = maxVal;
   if (val < minVal) val = minVal;
   return val;
}

void Platform_Initialise()
{

}

void Platform_Finalise()
{

}
<|endoftext|>