<commit_before>//     Copyright Toru Niina 2019.
// Distributed under the MIT License.
#ifndef TOML11_SERIALIZER_HPP
#define TOML11_SERIALIZER_HPP
#include "value.hpp"
#include "lexer.hpp"
#include <limits>

namespace toml
{

struct serializer
{
    serializer(const std::size_t w              = 80,
               const int         float_prec     = std::numeric_limits<toml::floating>::max_digits10,
               const bool        can_be_inlined = false,
               std::vector<toml::key> ks        = {})
        : can_be_inlined_(can_be_inlined), float_prec_(float_prec), width_(w),
          keys_(std::move(ks))
    {}
    ~serializer() = default;

    std::string operator()(const toml::boolean& b) const
    {
        return b ? "true" : "false";
    }
    std::string operator()(const integer i) const
    {
        return std::to_string(i);
    }
    std::string operator()(const toml::floating f) const
    {
        std::string token = [=] {
            // every float value needs decimal point (or exponent).
            std::ostringstream oss;
            oss << std::setprecision(float_prec_) << std::showpoint << f;
            return oss.str();
        }();

        if(token.back() == '.') // 1. => 1.0
        {
            token += '0';
        }
        const auto e = std::find_if(token.cbegin(), token.cend(),
            [](const char c) -> bool {
                return c == 'E' || c == 'e';
            });
        if(e == token.cend())
        {
            return token; // there is no exponent part. just return it.
        }

        // zero-prefix in an exponent is not allowed in TOML.
        // remove it if it exists.
        bool        sign_exists = false;
        std::size_t zero_prefix = 0;
        for(auto iter = std::next(e), iend = token.cend(); iter != iend; ++iter)
        {
            if(*iter == '+' || *iter == '-'){sign_exists = true; continue;}
            if(*iter == '0'){zero_prefix += 1;}
            else {break;}
        }
        if(zero_prefix != 0)
        {
            const auto offset = std::distance(token.cbegin(), e) +
                               (sign_exists ? 2 : 1);
            token.erase(offset, zero_prefix);
        }
        return token;
    }
    std::string operator()(const string& s) const
    {
        if(s.kind == string_t::basic)
        {
            if(std::find(s.str.cbegin(), s.str.cend(), '\n') != s.str.cend())
            {
                // if linefeed is contained, make it multiline-string.
                const std::string open("\"\"\"\n");
                const std::string close("\\\n\"\"\"");
                return open + this->escape_ml_basic_string(s.str) + close;
            }

            // no linefeed. try to make it oneline-string.
            std::string oneline = this->escape_basic_string(s.str);
            if(oneline.size() + 2 < width_ || width_ < 2)
            {
                const std::string quote("\"");
                return quote + oneline + quote;
            }

            // the line is too long compared to the specified width.
            // split it into multiple lines.
            std::string token("\"\"\"\n");
            while(!oneline.empty())
            {
                if(oneline.size() < width_)
                {
                    token += oneline;
                    oneline.clear();
                }
                else if(oneline.at(width_-2) == '\\')
                {
                    token += oneline.substr(0, width_-2);
                    token += "\\\n";
                    oneline.erase(0, width_-2);
                }
                else
                {
                    token += oneline.substr(0, width_-1);
                    token += "\\\n";
                    oneline.erase(0, width_-1);
                }
            }
            return token + std::string("\\\n\"\"\"");
        }
        else // the string `s` is literal-string.
        {
            if(std::find(s.str.cbegin(), s.str.cend(), '\n') != s.str.cend() ||
               std::find(s.str.cbegin(), s.str.cend(), '\'') != s.str.cend() )
            {
                const std::string open("'''\n");
                const std::string close("'''");
                return open + s.str + close;
            }
            else
            {
                const std::string quote("'");
                return quote + s.str + quote;
            }
        }
    }

    std::string operator()(const local_date& d) const
    {
        std::ostringstream oss;
        oss << d;
        return oss.str();
    }
    std::string operator()(const local_time& t) const
    {
        std::ostringstream oss;
        oss << t;
        return oss.str();
    }
    std::string operator()(const local_datetime& dt) const
    {
        std::ostringstream oss;
        oss << dt;
        return oss.str();
    }
    std::string operator()(const offset_datetime& odt) const
    {
        std::ostringstream oss;
        oss << odt;
        return oss.str();
    }

    std::string operator()(const array& v) const
    {
        if(!v.empty() && v.front().is(value_t::Table))// v is an array of tables
        {
            // if it's not inlined, we need to add `[[table.key]]`.
            // but if it can be inlined, we need `table.key = [...]`.
            if(this->can_be_inlined_)
            {
                std::string token;
                if(!keys_.empty())
                {
                    token += this->serialize_key(keys_.back());
                    token += " = ";
                }
                bool width_exceeds = false;
                token += "[\n";
                for(const auto& item : v)
                {
                    const auto t =
                        this->make_inline_table(item.cast<value_t::Table>());

                    if(t.size() + 1 > width_ || // +1 for the last comma {...},
                       std::find(t.cbegin(), t.cend(), '\n') != t.cend())
                    {
                        width_exceeds = true;
                        break;
                    }
                    token += t;
                    token += ",\n";
                }
                if(!width_exceeds)
                {
                    token += "]\n";
                    return token;
                }
                // if width_exceeds, serialize it as [[array.of.tables]].
            }

            std::string token;
            for(const auto& item : v)
            {
                token += "[[";
                token += this->serialize_dotted_key(keys_);
                token += "]]\n";
                token += this->make_multiline_table(item.cast<value_t::Table>());
            }
            return token;
        }
        if(v.empty())
        {
            return std::string("[]");
        }

        // not an array of tables. normal array. first, try to make it inline.
        {
            const auto inl = this->make_inline_array(v);
            if(inl.size() < this->width_ &&
               std::find(inl.cbegin(), inl.cend(), '\n') == inl.cend())
            {
                return inl;
            }
        }

        // if the length exceeds this->width_, print multiline array
        std::string token;
        std::string current_line;
        token += "[\n";
        for(const auto& item : v)
        {
            auto next_elem = toml::visit(*this, item);
            // newline between array-value and comma is not allowed
            if(next_elem.back() == '\n'){next_elem.pop_back();}

            if(current_line.size() + next_elem.size() + 1 < this->width_)
            {
                current_line += next_elem;
                current_line += ',';
            }
            else if(current_line.empty())
            {
                // the next elem cannot be within the width.
                token += next_elem;
                token += ",\n";
                // keep current line empty
            }
            else // current_line has some tokens and it exceeds width
            {
                assert(current_line.back() == ',');
                token += current_line;
                token += '\n';
                current_line = next_elem;
                current_line += ',';
            }
        }
        if(!current_line.empty())
        {
            if(current_line.back() != '\n') {current_line += '\n';}
            token += current_line;
        }
        token += "]\n";
        return token;
    }

    std::string operator()(const table& v) const
    {
        if(this->can_be_inlined_)
        {
            std::string token;
            if(!this->keys_.empty())
            {
                token += this->serialize_key(this->keys_.back());
                token += " = ";
            }
            token += this->make_inline_table(v);
            if(token.size() < this->width_)
            {
                return token;
            }
        }

        std::string token;
        if(!keys_.empty())
        {
            token += '[';
            token += this->serialize_dotted_key(keys_);
            token += "]\n";
        }
        token += this->make_multiline_table(v);
        return token;
    }

  private:

    std::string serialize_key(const toml::key& key) const
    {
        detail::location<toml::key> loc(key, key);
        detail::lex_unquoted_key::invoke(loc);
        if(loc.iter() == loc.end())
        {
            return key; // all the tokens are consumed. the key is unquoted-key.
        }
        std::string token("\"");
        token += this->escape_basic_string(key);
        token += "\"";
        return token;
    }

    std::string serialize_dotted_key(const std::vector<toml::key>& keys) const
    {
        std::string token;
        if(keys.empty()){return token;}

        for(const auto& k : keys)
        {
            token += this->serialize_key(k);
            token += '.';
        }
        token.erase(token.size() - 1, 1); // remove trailing `.`
        return token;
    }

    std::string escape_basic_string(const std::string& s) const
    {
        //XXX assuming `s` is a valid utf-8 sequence.
        std::string retval;
        for(const char c : s)
        {
            switch(c)
            {
                case '\\': {retval += "\\\\"; break;}
                case '\"': {retval += "\\\""; break;}
                case '\b': {retval += "\\b";  break;}
                case '\t': {retval += "\\t";  break;}
                case '\f': {retval += "\\f";  break;}
                case '\n': {retval += "\\n";  break;}
                case '\r': {retval += "\\r";  break;}
                default  : {retval += c;      break;}
            }
        }
        return retval;
    }

    std::string escape_ml_basic_string(const std::string& s) const
    {
        std::string retval;
        for(auto i=s.cbegin(), e=s.cend(); i!=e; ++i)
        {
            switch(*i)
            {
                case '\\': {retval += "\\\\"; break;}
                case '\"': {retval += "\\\""; break;}
                case '\b': {retval += "\\b";  break;}
                case '\t': {retval += "\\t";  break;}
                case '\f': {retval += "\\f";  break;}
                case '\n': {retval += "\n";   break;}
                case '\r':
                {
                    if(std::next(i) != e && *std::next(i) == '\n')
                    {
                        retval += "\r\n";
                        ++i;
                    }
                    else
                    {
                        retval += "\\r";
                    }
                    break;
                }
                default: {retval += *i; break;}
            }
        }
        return retval;
    }

    std::string make_inline_array(const array& v) const
    {
        std::string token;
        token += '[';
        bool is_first = true;
        for(const auto& item : v)
        {
            if(is_first) {is_first = false;} else {token += ',';}
            token += visit(serializer(std::numeric_limits<std::size_t>::max(),
                                      this->float_prec_, true), item);
        }
        token += ']';
        return token;
    }

    std::string make_inline_table(const table& v) const
    {
        assert(this->can_be_inlined_);
        std::string token;
        token += '{';
        bool is_first = true;
        for(const auto& kv : v)
        {
            // in inline tables, trailing comma is not allowed (toml-lang #569).
            if(is_first) {is_first = false;} else {token += ',';}
            token += this->serialize_key(kv.first);
            token += '=';
            token += visit(serializer(std::numeric_limits<std::size_t>::max(),
                                      this->float_prec_, true), kv.second);
        }
        token += '}';
        return token;
    }

    std::string make_multiline_table(const table& v) const
    {
        std::string token;

        // print non-table stuff first. because after printing [foo.bar], the
        // remaining non-table values will be assigned into [foo.bar], not [foo]
        for(const auto kv : v)
        {
            if(kv.second.is(value_t::Table) || is_array_of_tables(kv.second))
            {
                continue;
            }

            const auto key_and_sep    = this->serialize_key(kv.first) + " = ";
            const auto residual_width = (this->width_ > key_and_sep.size()) ?
                                        this->width_ - key_and_sep.size() : 0;
            token += key_and_sep;
            token += visit(serializer(residual_width, this->float_prec_, true),
                           kv.second);
            if(token.back() != '\n')
            {
                token += '\n';
            }
        }

        // normal tables / array of tables

        // after multiline table appeared, the other tables cannot be inline
        // because the table would be assigned into the table.
        // [foo]
        // ...
        // bar = {...} # <- bar will be a member of [foo].
        bool multiline_table_printed = false;
        for(const auto& kv : v)
        {
            if(!kv.second.is(value_t::Table) && !is_array_of_tables(kv.second))
            {
                continue; // other stuff are already serialized. skip them.
            }

            std::vector<toml::key> ks(this->keys_);
            ks.push_back(kv.first);

            auto tmp = visit(serializer(
                this->width_, this->float_prec_, !multiline_table_printed, ks),
                kv.second);

            if((!multiline_table_printed) &&
               std::find(tmp.cbegin(), tmp.cend(), '\n') != tmp.cend())
            {
                multiline_table_printed = true;
            }
            else
            {
                // still inline tables only.
                tmp += '\n';
            }
            token += tmp;
        }
        return token;
    }

    bool is_array_of_tables(const value& v) const
    {
        if(!v.is(value_t::Array)) {return false;}

        const auto& a = v.cast<value_t::Array>();
        return !a.empty() && a.front().is(value_t::Table);
    }

  private:

    bool        can_be_inlined_;
    int         float_prec_;
    std::size_t width_;
    std::vector<toml::key> keys_;
};

inline std::string
format(const value& v, std::size_t w = 80,
       int fprec = std::numeric_limits<toml::floating>::max_digits10)
{
    return visit(serializer(w, fprec, true), v);
}
inline std::string
format(const table& t, std::size_t w = 80,
       int fprec = std::numeric_limits<toml::floating>::max_digits10)
{
    return serializer(w, fprec, true)(t);
}

template<typename charT, typename traits>
std::basic_ostream<charT, traits>&
operator<<(std::basic_ostream<charT, traits>& os, const value& v)
{
    // get status of std::setw().
    const std::size_t w     = os.width();
    const int         fprec = os.precision();

    // the root object can't be an inline table. so pass `false`.
    os << visit(serializer(w, fprec, false), v);
    return os;
}

} // toml
#endif// TOML11_SERIALIZER_HPP
<commit_msg>fix: reset stream width before printing<commit_after>//     Copyright Toru Niina 2019.
// Distributed under the MIT License.
#ifndef TOML11_SERIALIZER_HPP
#define TOML11_SERIALIZER_HPP
#include "value.hpp"
#include "lexer.hpp"
#include <limits>

namespace toml
{

struct serializer
{
    serializer(const std::size_t w              = 80,
               const int         float_prec     = std::numeric_limits<toml::floating>::max_digits10,
               const bool        can_be_inlined = false,
               std::vector<toml::key> ks        = {})
        : can_be_inlined_(can_be_inlined), float_prec_(float_prec), width_(w),
          keys_(std::move(ks))
    {}
    ~serializer() = default;

    std::string operator()(const toml::boolean& b) const
    {
        return b ? "true" : "false";
    }
    std::string operator()(const integer i) const
    {
        return std::to_string(i);
    }
    std::string operator()(const toml::floating f) const
    {
        std::string token = [=] {
            // every float value needs decimal point (or exponent).
            std::ostringstream oss;
            oss << std::setprecision(float_prec_) << std::showpoint << f;
            return oss.str();
        }();

        if(token.back() == '.') // 1. => 1.0
        {
            token += '0';
        }
        const auto e = std::find_if(token.cbegin(), token.cend(),
            [](const char c) -> bool {
                return c == 'E' || c == 'e';
            });
        if(e == token.cend())
        {
            return token; // there is no exponent part. just return it.
        }

        // zero-prefix in an exponent is not allowed in TOML.
        // remove it if it exists.
        bool        sign_exists = false;
        std::size_t zero_prefix = 0;
        for(auto iter = std::next(e), iend = token.cend(); iter != iend; ++iter)
        {
            if(*iter == '+' || *iter == '-'){sign_exists = true; continue;}
            if(*iter == '0'){zero_prefix += 1;}
            else {break;}
        }
        if(zero_prefix != 0)
        {
            const auto offset = std::distance(token.cbegin(), e) +
                               (sign_exists ? 2 : 1);
            token.erase(offset, zero_prefix);
        }
        return token;
    }
    std::string operator()(const string& s) const
    {
        if(s.kind == string_t::basic)
        {
            if(std::find(s.str.cbegin(), s.str.cend(), '\n') != s.str.cend())
            {
                // if linefeed is contained, make it multiline-string.
                const std::string open("\"\"\"\n");
                const std::string close("\\\n\"\"\"");
                return open + this->escape_ml_basic_string(s.str) + close;
            }

            // no linefeed. try to make it oneline-string.
            std::string oneline = this->escape_basic_string(s.str);
            if(oneline.size() + 2 < width_ || width_ < 2)
            {
                const std::string quote("\"");
                return quote + oneline + quote;
            }

            // the line is too long compared to the specified width.
            // split it into multiple lines.
            std::string token("\"\"\"\n");
            while(!oneline.empty())
            {
                if(oneline.size() < width_)
                {
                    token += oneline;
                    oneline.clear();
                }
                else if(oneline.at(width_-2) == '\\')
                {
                    token += oneline.substr(0, width_-2);
                    token += "\\\n";
                    oneline.erase(0, width_-2);
                }
                else
                {
                    token += oneline.substr(0, width_-1);
                    token += "\\\n";
                    oneline.erase(0, width_-1);
                }
            }
            return token + std::string("\\\n\"\"\"");
        }
        else // the string `s` is literal-string.
        {
            if(std::find(s.str.cbegin(), s.str.cend(), '\n') != s.str.cend() ||
               std::find(s.str.cbegin(), s.str.cend(), '\'') != s.str.cend() )
            {
                const std::string open("'''\n");
                const std::string close("'''");
                return open + s.str + close;
            }
            else
            {
                const std::string quote("'");
                return quote + s.str + quote;
            }
        }
    }

    std::string operator()(const local_date& d) const
    {
        std::ostringstream oss;
        oss << d;
        return oss.str();
    }
    std::string operator()(const local_time& t) const
    {
        std::ostringstream oss;
        oss << t;
        return oss.str();
    }
    std::string operator()(const local_datetime& dt) const
    {
        std::ostringstream oss;
        oss << dt;
        return oss.str();
    }
    std::string operator()(const offset_datetime& odt) const
    {
        std::ostringstream oss;
        oss << odt;
        return oss.str();
    }

    std::string operator()(const array& v) const
    {
        if(!v.empty() && v.front().is(value_t::Table))// v is an array of tables
        {
            // if it's not inlined, we need to add `[[table.key]]`.
            // but if it can be inlined, we need `table.key = [...]`.
            if(this->can_be_inlined_)
            {
                std::string token;
                if(!keys_.empty())
                {
                    token += this->serialize_key(keys_.back());
                    token += " = ";
                }
                bool width_exceeds = false;
                token += "[\n";
                for(const auto& item : v)
                {
                    const auto t =
                        this->make_inline_table(item.cast<value_t::Table>());

                    if(t.size() + 1 > width_ || // +1 for the last comma {...},
                       std::find(t.cbegin(), t.cend(), '\n') != t.cend())
                    {
                        width_exceeds = true;
                        break;
                    }
                    token += t;
                    token += ",\n";
                }
                if(!width_exceeds)
                {
                    token += "]\n";
                    return token;
                }
                // if width_exceeds, serialize it as [[array.of.tables]].
            }

            std::string token;
            for(const auto& item : v)
            {
                token += "[[";
                token += this->serialize_dotted_key(keys_);
                token += "]]\n";
                token += this->make_multiline_table(item.cast<value_t::Table>());
            }
            return token;
        }
        if(v.empty())
        {
            return std::string("[]");
        }

        // not an array of tables. normal array. first, try to make it inline.
        {
            const auto inl = this->make_inline_array(v);
            if(inl.size() < this->width_ &&
               std::find(inl.cbegin(), inl.cend(), '\n') == inl.cend())
            {
                return inl;
            }
        }

        // if the length exceeds this->width_, print multiline array
        std::string token;
        std::string current_line;
        token += "[\n";
        for(const auto& item : v)
        {
            auto next_elem = toml::visit(*this, item);
            // newline between array-value and comma is not allowed
            if(next_elem.back() == '\n'){next_elem.pop_back();}

            if(current_line.size() + next_elem.size() + 1 < this->width_)
            {
                current_line += next_elem;
                current_line += ',';
            }
            else if(current_line.empty())
            {
                // the next elem cannot be within the width.
                token += next_elem;
                token += ",\n";
                // keep current line empty
            }
            else // current_line has some tokens and it exceeds width
            {
                assert(current_line.back() == ',');
                token += current_line;
                token += '\n';
                current_line = next_elem;
                current_line += ',';
            }
        }
        if(!current_line.empty())
        {
            if(current_line.back() != '\n') {current_line += '\n';}
            token += current_line;
        }
        token += "]\n";
        return token;
    }

    std::string operator()(const table& v) const
    {
        if(this->can_be_inlined_)
        {
            std::string token;
            if(!this->keys_.empty())
            {
                token += this->serialize_key(this->keys_.back());
                token += " = ";
            }
            token += this->make_inline_table(v);
            if(token.size() < this->width_)
            {
                return token;
            }
        }

        std::string token;
        if(!keys_.empty())
        {
            token += '[';
            token += this->serialize_dotted_key(keys_);
            token += "]\n";
        }
        token += this->make_multiline_table(v);
        return token;
    }

  private:

    std::string serialize_key(const toml::key& key) const
    {
        detail::location<toml::key> loc(key, key);
        detail::lex_unquoted_key::invoke(loc);
        if(loc.iter() == loc.end())
        {
            return key; // all the tokens are consumed. the key is unquoted-key.
        }
        std::string token("\"");
        token += this->escape_basic_string(key);
        token += "\"";
        return token;
    }

    std::string serialize_dotted_key(const std::vector<toml::key>& keys) const
    {
        std::string token;
        if(keys.empty()){return token;}

        for(const auto& k : keys)
        {
            token += this->serialize_key(k);
            token += '.';
        }
        token.erase(token.size() - 1, 1); // remove trailing `.`
        return token;
    }

    std::string escape_basic_string(const std::string& s) const
    {
        //XXX assuming `s` is a valid utf-8 sequence.
        std::string retval;
        for(const char c : s)
        {
            switch(c)
            {
                case '\\': {retval += "\\\\"; break;}
                case '\"': {retval += "\\\""; break;}
                case '\b': {retval += "\\b";  break;}
                case '\t': {retval += "\\t";  break;}
                case '\f': {retval += "\\f";  break;}
                case '\n': {retval += "\\n";  break;}
                case '\r': {retval += "\\r";  break;}
                default  : {retval += c;      break;}
            }
        }
        return retval;
    }

    std::string escape_ml_basic_string(const std::string& s) const
    {
        std::string retval;
        for(auto i=s.cbegin(), e=s.cend(); i!=e; ++i)
        {
            switch(*i)
            {
                case '\\': {retval += "\\\\"; break;}
                case '\"': {retval += "\\\""; break;}
                case '\b': {retval += "\\b";  break;}
                case '\t': {retval += "\\t";  break;}
                case '\f': {retval += "\\f";  break;}
                case '\n': {retval += "\n";   break;}
                case '\r':
                {
                    if(std::next(i) != e && *std::next(i) == '\n')
                    {
                        retval += "\r\n";
                        ++i;
                    }
                    else
                    {
                        retval += "\\r";
                    }
                    break;
                }
                default: {retval += *i; break;}
            }
        }
        return retval;
    }

    std::string make_inline_array(const array& v) const
    {
        std::string token;
        token += '[';
        bool is_first = true;
        for(const auto& item : v)
        {
            if(is_first) {is_first = false;} else {token += ',';}
            token += visit(serializer(std::numeric_limits<std::size_t>::max(),
                                      this->float_prec_, true), item);
        }
        token += ']';
        return token;
    }

    std::string make_inline_table(const table& v) const
    {
        assert(this->can_be_inlined_);
        std::string token;
        token += '{';
        bool is_first = true;
        for(const auto& kv : v)
        {
            // in inline tables, trailing comma is not allowed (toml-lang #569).
            if(is_first) {is_first = false;} else {token += ',';}
            token += this->serialize_key(kv.first);
            token += '=';
            token += visit(serializer(std::numeric_limits<std::size_t>::max(),
                                      this->float_prec_, true), kv.second);
        }
        token += '}';
        return token;
    }

    std::string make_multiline_table(const table& v) const
    {
        std::string token;

        // print non-table stuff first. because after printing [foo.bar], the
        // remaining non-table values will be assigned into [foo.bar], not [foo]
        for(const auto kv : v)
        {
            if(kv.second.is(value_t::Table) || is_array_of_tables(kv.second))
            {
                continue;
            }

            const auto key_and_sep    = this->serialize_key(kv.first) + " = ";
            const auto residual_width = (this->width_ > key_and_sep.size()) ?
                                        this->width_ - key_and_sep.size() : 0;
            token += key_and_sep;
            token += visit(serializer(residual_width, this->float_prec_, true),
                           kv.second);
            if(token.back() != '\n')
            {
                token += '\n';
            }
        }

        // normal tables / array of tables

        // after multiline table appeared, the other tables cannot be inline
        // because the table would be assigned into the table.
        // [foo]
        // ...
        // bar = {...} # <- bar will be a member of [foo].
        bool multiline_table_printed = false;
        for(const auto& kv : v)
        {
            if(!kv.second.is(value_t::Table) && !is_array_of_tables(kv.second))
            {
                continue; // other stuff are already serialized. skip them.
            }

            std::vector<toml::key> ks(this->keys_);
            ks.push_back(kv.first);

            auto tmp = visit(serializer(
                this->width_, this->float_prec_, !multiline_table_printed, ks),
                kv.second);

            if((!multiline_table_printed) &&
               std::find(tmp.cbegin(), tmp.cend(), '\n') != tmp.cend())
            {
                multiline_table_printed = true;
            }
            else
            {
                // still inline tables only.
                tmp += '\n';
            }
            token += tmp;
        }
        return token;
    }

    bool is_array_of_tables(const value& v) const
    {
        if(!v.is(value_t::Array)) {return false;}

        const auto& a = v.cast<value_t::Array>();
        return !a.empty() && a.front().is(value_t::Table);
    }

  private:

    bool        can_be_inlined_;
    int         float_prec_;
    std::size_t width_;
    std::vector<toml::key> keys_;
};

inline std::string
format(const value& v, std::size_t w = 80,
       int fprec = std::numeric_limits<toml::floating>::max_digits10)
{
    return visit(serializer(w, fprec, true), v);
}
inline std::string
format(const table& t, std::size_t w = 80,
       int fprec = std::numeric_limits<toml::floating>::max_digits10)
{
    return serializer(w, fprec, true)(t);
}

template<typename charT, typename traits>
std::basic_ostream<charT, traits>&
operator<<(std::basic_ostream<charT, traits>& os, const value& v)
{
    // get status of std::setw().
    const std::size_t w     = os.width();
    const int         fprec = os.precision();
    os.width(0);
    // the root object can't be an inline table. so pass `false`.
    os << visit(serializer(w, fprec, false), v);
    return os;
}

} // toml
#endif// TOML11_SERIALIZER_HPP
<|endoftext|>


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

#include "remoting/host/event_executor.h"

#include <windows.h>

#include "base/bind.h"
#include "base/compiler_specific.h"
#include "base/message_loop.h"
#include "remoting/host/capturer.h"
#include "remoting/proto/event.pb.h"
#include "ui/base/keycodes/keyboard_codes.h"

namespace remoting {

using protocol::ClipboardEvent;
using protocol::KeyEvent;
using protocol::MouseEvent;

namespace {

// USB to XKB keycode map table.
#define USB_KEYMAP(usb, xkb, win, mac) {usb, win}
#define INVALID_KEYCODE 0x0000
#include "remoting/host/usb_keycode_map.h"
#undef USB_KEYMAP

// A class to generate events on Windows.
class EventExecutorWin : public EventExecutor {
 public:
  EventExecutorWin(MessageLoop* message_loop, Capturer* capturer);
  virtual ~EventExecutorWin() {}

  // ClipboardStub interface.
  virtual void InjectClipboardEvent(const ClipboardEvent& event) OVERRIDE;

  // InputStub interface.
  virtual void InjectKeyEvent(const KeyEvent& event) OVERRIDE;
  virtual void InjectMouseEvent(const MouseEvent& event) OVERRIDE;

 private:
  void HandleKey(const KeyEvent& event);
  void HandleMouse(const MouseEvent& event);

  MessageLoop* message_loop_;
  Capturer* capturer_;

  DISALLOW_COPY_AND_ASSIGN(EventExecutorWin);
};

EventExecutorWin::EventExecutorWin(MessageLoop* message_loop,
                                   Capturer* capturer)
    : message_loop_(message_loop),
      capturer_(capturer) {
}

void EventExecutorWin::InjectClipboardEvent(const ClipboardEvent& event) {
  // TODO(simonmorris): Implement clipboard injection.
}

void EventExecutorWin::InjectKeyEvent(const KeyEvent& event) {
  if (MessageLoop::current() != message_loop_) {
    message_loop_->PostTask(
        FROM_HERE,
        base::Bind(&EventExecutorWin::InjectKeyEvent, base::Unretained(this),
                   event));
    return;
  }

  HandleKey(event);
}

void EventExecutorWin::InjectMouseEvent(const MouseEvent& event) {
  if (MessageLoop::current() != message_loop_) {
    message_loop_->PostTask(
        FROM_HERE,
        base::Bind(&EventExecutorWin::InjectMouseEvent, base::Unretained(this),
                   event));
    return;
  }

  HandleMouse(event);
}

uint16_t UsbKeycodeToWinScancode(uint32_t usb_keycode) {
  for (int i = 0; i < arraysize(usb_keycode_map); i++) {
    if (usb_keycode_map[i].usb_keycode == usb_keycode)
      return usb_keycode_map[i].native_keycode;
  }

  return INVALID_KEYCODE;
}

void EventExecutorWin::HandleKey(const KeyEvent& event) {
  int key = event.keycode();
  bool down = event.pressed();

  // Calculate scan code from key event.
  int scancode = INVALID_KEYCODE;
  if (event.has_usb_keycode() && event.usb_keycode() != 0) {
    int scancode = UsbKeycodeToWinScancode(event.usb_keycode());
    LOG(INFO) << std::hex << "Host received keycode: " << event.keycode()
            << " usb_keycode: " << event.usb_keycode()
            << " to scancode: " << scancode
            << std::dec;
  } else {
    HKL hkl = GetKeyboardLayout(0);
    scancode = MapVirtualKeyEx(key, MAPVK_VK_TO_VSC_EX, hkl);
  }

  if (scancode == INVALID_KEYCODE)
    return;

  INPUT input;
  memset(&input, 0, sizeof(input));

  input.type = INPUT_KEYBOARD;
  input.ki.time = 0;
  input.ki.wVk = key;
  input.ki.wScan = scancode;

  // Flag to mark extended 'e0' key scancodes. Without this, the left and
  // right windows keys will not be handled properly (on US keyboard).
  if ((scancode & 0xFF00) == 0xE000) {
    input.ki.dwFlags |= KEYEVENTF_EXTENDEDKEY;
  }

  // Flag to mark keyup events. Default is keydown.
  if (!down) {
    input.ki.dwFlags |= KEYEVENTF_KEYUP;
  }

  if (SendInput(1, &input, sizeof(INPUT)) == 0) {
    LOG_GETLASTERROR(ERROR) << "Failed to inject a key event";
  }
}

void EventExecutorWin::HandleMouse(const MouseEvent& event) {
  // TODO(garykac) Collapse mouse (x,y) and button events into a single
  // input event when possible.
  if (event.has_x() && event.has_y()) {
    int x = event.x();
    int y = event.y();

    INPUT input;
    input.type = INPUT_MOUSE;
    input.mi.time = 0;
    SkISize screen_size = capturer_->size_most_recent();
    if ((screen_size.width() > 1) && (screen_size.height() > 1)) {
      input.mi.dx = static_cast<int>((x * 65535) / (screen_size.width() - 1));
      input.mi.dy = static_cast<int>((y * 65535) / (screen_size.height() - 1));
      input.mi.dwFlags = MOUSEEVENTF_MOVE | MOUSEEVENTF_ABSOLUTE;
      if (SendInput(1, &input, sizeof(INPUT)) == 0) {
        LOG_GETLASTERROR(ERROR) << "Failed to inject a mouse move event";
      }
    }
  }

  if (event.has_wheel_offset_x() && event.has_wheel_offset_y()) {
    INPUT wheel;
    wheel.type = INPUT_MOUSE;
    wheel.mi.time = 0;

    int dx = event.wheel_offset_x();
    int dy = event.wheel_offset_y();

    if (dx != 0) {
      wheel.mi.mouseData = dx * WHEEL_DELTA;
      wheel.mi.dwFlags = MOUSEEVENTF_HWHEEL;
      if (SendInput(1, &wheel, sizeof(INPUT)) == 0) {
        LOG_GETLASTERROR(ERROR) << "Failed to inject a mouse wheel(x) event";
      }
    }
    if (dy != 0) {
      wheel.mi.mouseData = dy * WHEEL_DELTA;
      wheel.mi.dwFlags = MOUSEEVENTF_WHEEL;
      if (SendInput(1, &wheel, sizeof(INPUT)) == 0) {
        LOG_GETLASTERROR(ERROR) << "Failed to inject a mouse wheel(y) event";
      }
    }
  }

  if (event.has_button() && event.has_button_down()) {
    INPUT button_event;
    button_event.type = INPUT_MOUSE;
    button_event.mi.time = 0;
    button_event.mi.dx = 0;
    button_event.mi.dy = 0;

    MouseEvent::MouseButton button = event.button();
    bool down = event.button_down();
    if (button == MouseEvent::BUTTON_LEFT) {
      button_event.mi.dwFlags =
          down ? MOUSEEVENTF_LEFTDOWN : MOUSEEVENTF_LEFTUP;
    } else if (button == MouseEvent::BUTTON_MIDDLE) {
      button_event.mi.dwFlags =
          down ? MOUSEEVENTF_MIDDLEDOWN : MOUSEEVENTF_MIDDLEUP;
    } else if (button == MouseEvent::BUTTON_RIGHT) {
      button_event.mi.dwFlags =
          down ? MOUSEEVENTF_RIGHTDOWN : MOUSEEVENTF_RIGHTUP;
    } else {
      button_event.mi.dwFlags =
          down ? MOUSEEVENTF_LEFTDOWN : MOUSEEVENTF_LEFTUP;
    }

    if (SendInput(1, &button_event, sizeof(INPUT)) == 0) {
      LOG_GETLASTERROR(ERROR) << "Failed to inject a mouse button event";
    }
  }
}

}  // namespace

scoped_ptr<protocol::HostEventStub> EventExecutor::Create(
    MessageLoop* message_loop, Capturer* capturer) {
  return scoped_ptr<protocol::HostEventStub>(
      new EventExecutorWin(message_loop, capturer));
}

}  // namespace remoting
<commit_msg>[Chromoting] Fix bug with handling USB keycodes and remove extra logging.<commit_after>// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "remoting/host/event_executor.h"

#include <windows.h>

#include "base/bind.h"
#include "base/compiler_specific.h"
#include "base/message_loop.h"
#include "remoting/host/capturer.h"
#include "remoting/proto/event.pb.h"
#include "ui/base/keycodes/keyboard_codes.h"

namespace remoting {

using protocol::ClipboardEvent;
using protocol::KeyEvent;
using protocol::MouseEvent;

namespace {

// USB to XKB keycode map table.
#define USB_KEYMAP(usb, xkb, win, mac) {usb, win}
#define INVALID_KEYCODE 0x0000
#include "remoting/host/usb_keycode_map.h"
#undef USB_KEYMAP

// A class to generate events on Windows.
class EventExecutorWin : public EventExecutor {
 public:
  EventExecutorWin(MessageLoop* message_loop, Capturer* capturer);
  virtual ~EventExecutorWin() {}

  // ClipboardStub interface.
  virtual void InjectClipboardEvent(const ClipboardEvent& event) OVERRIDE;

  // InputStub interface.
  virtual void InjectKeyEvent(const KeyEvent& event) OVERRIDE;
  virtual void InjectMouseEvent(const MouseEvent& event) OVERRIDE;

 private:
  void HandleKey(const KeyEvent& event);
  void HandleMouse(const MouseEvent& event);

  MessageLoop* message_loop_;
  Capturer* capturer_;

  DISALLOW_COPY_AND_ASSIGN(EventExecutorWin);
};

EventExecutorWin::EventExecutorWin(MessageLoop* message_loop,
                                   Capturer* capturer)
    : message_loop_(message_loop),
      capturer_(capturer) {
}

void EventExecutorWin::InjectClipboardEvent(const ClipboardEvent& event) {
  // TODO(simonmorris): Implement clipboard injection.
}

void EventExecutorWin::InjectKeyEvent(const KeyEvent& event) {
  if (MessageLoop::current() != message_loop_) {
    message_loop_->PostTask(
        FROM_HERE,
        base::Bind(&EventExecutorWin::InjectKeyEvent, base::Unretained(this),
                   event));
    return;
  }

  HandleKey(event);
}

void EventExecutorWin::InjectMouseEvent(const MouseEvent& event) {
  if (MessageLoop::current() != message_loop_) {
    message_loop_->PostTask(
        FROM_HERE,
        base::Bind(&EventExecutorWin::InjectMouseEvent, base::Unretained(this),
                   event));
    return;
  }

  HandleMouse(event);
}

uint16_t UsbKeycodeToWinScancode(uint32_t usb_keycode) {
  for (int i = 0; i < arraysize(usb_keycode_map); i++) {
    if (usb_keycode_map[i].usb_keycode == usb_keycode)
      return usb_keycode_map[i].native_keycode;
  }

  return INVALID_KEYCODE;
}

void EventExecutorWin::HandleKey(const KeyEvent& event) {
  int key = event.keycode();
  bool down = event.pressed();

  // Calculate scan code from key event.
  int scancode = INVALID_KEYCODE;
  if (event.has_usb_keycode() && event.usb_keycode() != 0) {
    scancode = UsbKeycodeToWinScancode(event.usb_keycode());
    LOG(INFO) << std::hex << "Host received keycode: " << event.keycode()
            << " usb_keycode: " << event.usb_keycode()
            << " to scancode: " << scancode
            << std::dec;
  } else {
    HKL hkl = GetKeyboardLayout(0);
    scancode = MapVirtualKeyEx(key, MAPVK_VK_TO_VSC_EX, hkl);
  }

  if (scancode == INVALID_KEYCODE)
    return;

  INPUT input;
  memset(&input, 0, sizeof(input));

  input.type = INPUT_KEYBOARD;
  input.ki.time = 0;
  input.ki.wVk = key;
  input.ki.wScan = scancode;

  // Flag to mark extended 'e0' key scancodes. Without this, the left and
  // right windows keys will not be handled properly (on US keyboard).
  if ((scancode & 0xFF00) == 0xE000) {
    input.ki.dwFlags |= KEYEVENTF_EXTENDEDKEY;
  }

  // Flag to mark keyup events. Default is keydown.
  if (!down) {
    input.ki.dwFlags |= KEYEVENTF_KEYUP;
  }

  if (SendInput(1, &input, sizeof(INPUT)) == 0) {
    LOG_GETLASTERROR(ERROR) << "Failed to inject a key event";
  }
}

void EventExecutorWin::HandleMouse(const MouseEvent& event) {
  // TODO(garykac) Collapse mouse (x,y) and button events into a single
  // input event when possible.
  if (event.has_x() && event.has_y()) {
    int x = event.x();
    int y = event.y();

    INPUT input;
    input.type = INPUT_MOUSE;
    input.mi.time = 0;
    SkISize screen_size = capturer_->size_most_recent();
    if ((screen_size.width() > 1) && (screen_size.height() > 1)) {
      input.mi.dx = static_cast<int>((x * 65535) / (screen_size.width() - 1));
      input.mi.dy = static_cast<int>((y * 65535) / (screen_size.height() - 1));
      input.mi.dwFlags = MOUSEEVENTF_MOVE | MOUSEEVENTF_ABSOLUTE;
      if (SendInput(1, &input, sizeof(INPUT)) == 0) {
        LOG_GETLASTERROR(ERROR) << "Failed to inject a mouse move event";
      }
    }
  }

  if (event.has_wheel_offset_x() && event.has_wheel_offset_y()) {
    INPUT wheel;
    wheel.type = INPUT_MOUSE;
    wheel.mi.time = 0;

    int dx = event.wheel_offset_x();
    int dy = event.wheel_offset_y();

    if (dx != 0) {
      wheel.mi.mouseData = dx * WHEEL_DELTA;
      wheel.mi.dwFlags = MOUSEEVENTF_HWHEEL;
      if (SendInput(1, &wheel, sizeof(INPUT)) == 0) {
        LOG_GETLASTERROR(ERROR) << "Failed to inject a mouse wheel(x) event";
      }
    }
    if (dy != 0) {
      wheel.mi.mouseData = dy * WHEEL_DELTA;
      wheel.mi.dwFlags = MOUSEEVENTF_WHEEL;
      if (SendInput(1, &wheel, sizeof(INPUT)) == 0) {
        LOG_GETLASTERROR(ERROR) << "Failed to inject a mouse wheel(y) event";
      }
    }
  }

  if (event.has_button() && event.has_button_down()) {
    INPUT button_event;
    button_event.type = INPUT_MOUSE;
    button_event.mi.time = 0;
    button_event.mi.dx = 0;
    button_event.mi.dy = 0;

    MouseEvent::MouseButton button = event.button();
    bool down = event.button_down();
    if (button == MouseEvent::BUTTON_LEFT) {
      button_event.mi.dwFlags =
          down ? MOUSEEVENTF_LEFTDOWN : MOUSEEVENTF_LEFTUP;
    } else if (button == MouseEvent::BUTTON_MIDDLE) {
      button_event.mi.dwFlags =
          down ? MOUSEEVENTF_MIDDLEDOWN : MOUSEEVENTF_MIDDLEUP;
    } else if (button == MouseEvent::BUTTON_RIGHT) {
      button_event.mi.dwFlags =
          down ? MOUSEEVENTF_RIGHTDOWN : MOUSEEVENTF_RIGHTUP;
    } else {
      button_event.mi.dwFlags =
          down ? MOUSEEVENTF_LEFTDOWN : MOUSEEVENTF_LEFTUP;
    }

    if (SendInput(1, &button_event, sizeof(INPUT)) == 0) {
      LOG_GETLASTERROR(ERROR) << "Failed to inject a mouse button event";
    }
  }
}

}  // namespace

scoped_ptr<protocol::HostEventStub> EventExecutor::Create(
    MessageLoop* message_loop, Capturer* capturer) {
  return scoped_ptr<protocol::HostEventStub>(
      new EventExecutorWin(message_loop, capturer));
}

}  // namespace remoting
<|endoftext|>


<commit_before>// Copyright (C) 2017 Jérôme Leclercq
// This file is part of the "Nazara Development Kit"
// For conditions of distribution and use, see copyright notice in Prerequesites.hpp

#include <NDK/Entity.hpp>
#include <NDK/BaseComponent.hpp>
#include <NDK/World.hpp>

namespace Ndk
{
	/*!
	* \ingroup NDK
	* \class Ndk::Entity
	* \brief NDK class that represents an entity in a world
	*/

	/*!
	* \brief Constructs a Entity object by move semantic
	*
	* \param entity Entity to move into this
	*/

	Entity::Entity(Entity&& entity) :
	HandledObject(std::move(entity)),
	m_components(std::move(entity.m_components)),
	m_componentBits(std::move(entity.m_componentBits)),
	m_systemBits(std::move(entity.m_systemBits)),
	m_id(entity.m_id),
	m_world(entity.m_world),
	m_enabled(entity.m_enabled),
	m_valid(entity.m_valid)
	{
		entity.m_world = nullptr;
	}

	/*!
	* \brief Constructs a Entity object linked to a world and with an id
	*
	* \param world World in which the entity interact
	* \param id Identifier of the entity
	*/

	Entity::Entity(World* world, EntityId id) :
	m_id(id),
	m_world(world)
	{
	}

	/*!
	* \brief Destructs the object and calls Destroy
	*
	* \see Destroy
	*/

	Entity::~Entity()
	{
		if (m_world)
			Destroy();
	}

	/*!
	* \brief Adds a component to the entity
	* \return A reference to the newly added component
	*
	* \param componentPtr Component to add to the entity
	*
	* \remark Produces a NazaraAssert if component is nullptr
	*/

	BaseComponent& Entity::AddComponent(std::unique_ptr<BaseComponent>&& componentPtr)
	{
		NazaraAssert(componentPtr, "Component must be valid");

		ComponentIndex index = componentPtr->GetIndex();

		// We ensure that the vector has enough space
		if (index >= m_components.size())
			m_components.resize(index + 1);

		// Affectation and return of the component
		m_components[index] = std::move(componentPtr);
		m_componentBits.UnboundedSet(index);
		m_removedComponentBits.UnboundedReset(index);

		Invalidate();

		// We get the new component and we alert other existing components of the new one
		BaseComponent& component = *m_components[index].get();
		component.SetEntity(this);

		for (std::size_t i = m_componentBits.FindFirst(); i != m_componentBits.npos; i = m_componentBits.FindNext(i))
		{
			if (i != index)
				m_components[i]->OnComponentAttached(component);
		}

		return component;
	}

	/*!
	* \brief Clones the entity
	* \return The clone newly created
	*
	* \remark The close is enable by default, even if the original is disabled
	* \remark Produces a NazaraAssert if the entity is not valid
	*/

	const EntityHandle& Entity::Clone() const
	{
		NazaraAssert(IsValid(), "Invalid entity");

		return m_world->CloneEntity(m_id);
	}

	/*!
	* \brief Kills the entity
	*/

	void Entity::Kill()
	{
		m_world->KillEntity(this);
	}

	/*!
	* \brief Invalidates the entity
	*/

	void Entity::Invalidate()
	{
		// We alert everyone that we have been updated
		m_world->Invalidate(m_id);
	}

	/*!
	* \brief Creates the entity
	*/

	void Entity::Create()
	{
		m_enabled = true;
		m_valid = true;
	}

	/*!
	* \brief Destroys the entity
	*/

	void Entity::Destroy()
	{
		OnEntityDestruction(this);
		OnEntityDestruction.Clear();

		// We prepare components for entity destruction (some components needs this to handle some final callbacks while the entity is still valid)
		for (std::size_t i = m_componentBits.FindFirst(); i != m_componentBits.npos; i = m_componentBits.FindNext(i))
			m_components[i]->OnEntityDestruction();

		// Detach components while they're still attached to systems
		for (std::size_t i = m_componentBits.FindFirst(); i != m_componentBits.npos; i = m_componentBits.FindNext(i))
			m_components[i]->SetEntity(nullptr);

		// We alert each system
		for (std::size_t index = m_systemBits.FindFirst(); index != m_systemBits.npos; index = m_systemBits.FindNext(index))
		{
			auto sysIndex = static_cast<Ndk::SystemIndex>(index);

			if (m_world->HasSystem(sysIndex))
			{
				BaseSystem& system = m_world->GetSystem(sysIndex);
				system.RemoveEntity(this);
			}
		}
		m_systemBits.Clear();

		// Destroy components
		m_components.clear();
		m_componentBits.Reset();

		// And then free every handle
		UnregisterAllHandles();

		m_valid = false;
	}

	/*!
	* \brief Destroys a component by index
	*
	* \param index Index of the component
	*
	* \remark If component is not available, no action is performed
	*/

	void Entity::DestroyComponent(ComponentIndex index)
	{
		if (HasComponent(index))
		{
			// We get the component and we alert existing components of the deleted one
			BaseComponent& component = *m_components[index].get();
			for (std::size_t i = m_componentBits.FindFirst(); i != m_componentBits.npos; i = m_componentBits.FindNext(i))
			{
				if (i != index)
					m_components[i]->OnComponentDetached(component);
			}

			component.SetEntity(nullptr);

			m_components[index].reset();
			m_componentBits.Reset(index);
		}
	}

}
<commit_msg>Sdk/Entity: Fix removed components sometimes not being removed<commit_after>// Copyright (C) 2017 Jérôme Leclercq
// This file is part of the "Nazara Development Kit"
// For conditions of distribution and use, see copyright notice in Prerequesites.hpp

#include <NDK/Entity.hpp>
#include <NDK/BaseComponent.hpp>
#include <NDK/World.hpp>

namespace Ndk
{
	/*!
	* \ingroup NDK
	* \class Ndk::Entity
	* \brief NDK class that represents an entity in a world
	*/

	/*!
	* \brief Constructs a Entity object by move semantic
	*
	* \param entity Entity to move into this
	*/

	Entity::Entity(Entity&& entity) :
	HandledObject(std::move(entity)),
	m_components(std::move(entity.m_components)),
	m_componentBits(std::move(entity.m_componentBits)),
	m_removedComponentBits(std::move(entity.m_removedComponentBits)),
	m_systemBits(std::move(entity.m_systemBits)),
	m_id(entity.m_id),
	m_world(entity.m_world),
	m_enabled(entity.m_enabled),
	m_valid(entity.m_valid)
	{
		entity.m_world = nullptr;
	}

	/*!
	* \brief Constructs a Entity object linked to a world and with an id
	*
	* \param world World in which the entity interact
	* \param id Identifier of the entity
	*/

	Entity::Entity(World* world, EntityId id) :
	m_id(id),
	m_world(world)
	{
	}

	/*!
	* \brief Destructs the object and calls Destroy
	*
	* \see Destroy
	*/

	Entity::~Entity()
	{
		if (m_world)
			Destroy();
	}

	/*!
	* \brief Adds a component to the entity
	* \return A reference to the newly added component
	*
	* \param componentPtr Component to add to the entity
	*
	* \remark Produces a NazaraAssert if component is nullptr
	*/

	BaseComponent& Entity::AddComponent(std::unique_ptr<BaseComponent>&& componentPtr)
	{
		NazaraAssert(componentPtr, "Component must be valid");

		ComponentIndex index = componentPtr->GetIndex();

		// We ensure that the vector has enough space
		if (index >= m_components.size())
			m_components.resize(index + 1);

		// Affectation and return of the component
		m_components[index] = std::move(componentPtr);
		m_componentBits.UnboundedSet(index);
		m_removedComponentBits.UnboundedReset(index);

		Invalidate();

		// We get the new component and we alert other existing components of the new one
		BaseComponent& component = *m_components[index].get();
		component.SetEntity(this);

		for (std::size_t i = m_componentBits.FindFirst(); i != m_componentBits.npos; i = m_componentBits.FindNext(i))
		{
			if (i != index)
				m_components[i]->OnComponentAttached(component);
		}

		return component;
	}

	/*!
	* \brief Clones the entity
	* \return The clone newly created
	*
	* \remark The close is enable by default, even if the original is disabled
	* \remark Produces a NazaraAssert if the entity is not valid
	*/

	const EntityHandle& Entity::Clone() const
	{
		NazaraAssert(IsValid(), "Invalid entity");

		return m_world->CloneEntity(m_id);
	}

	/*!
	* \brief Kills the entity
	*/

	void Entity::Kill()
	{
		m_world->KillEntity(this);
	}

	/*!
	* \brief Invalidates the entity
	*/

	void Entity::Invalidate()
	{
		// We alert everyone that we have been updated
		m_world->Invalidate(m_id);
	}

	/*!
	* \brief Creates the entity
	*/

	void Entity::Create()
	{
		m_enabled = true;
		m_valid = true;
	}

	/*!
	* \brief Destroys the entity
	*/

	void Entity::Destroy()
	{
		OnEntityDestruction(this);
		OnEntityDestruction.Clear();

		// We prepare components for entity destruction (some components needs this to handle some final callbacks while the entity is still valid)
		for (std::size_t i = m_componentBits.FindFirst(); i != m_componentBits.npos; i = m_componentBits.FindNext(i))
			m_components[i]->OnEntityDestruction();

		// Detach components while they're still attached to systems
		for (std::size_t i = m_componentBits.FindFirst(); i != m_componentBits.npos; i = m_componentBits.FindNext(i))
			m_components[i]->SetEntity(nullptr);

		// We alert each system
		for (std::size_t index = m_systemBits.FindFirst(); index != m_systemBits.npos; index = m_systemBits.FindNext(index))
		{
			auto sysIndex = static_cast<Ndk::SystemIndex>(index);

			if (m_world->HasSystem(sysIndex))
			{
				BaseSystem& system = m_world->GetSystem(sysIndex);
				system.RemoveEntity(this);
			}
		}
		m_systemBits.Clear();

		// Destroy components
		m_components.clear();
		m_componentBits.Reset();

		// And then free every handle
		UnregisterAllHandles();

		m_valid = false;
	}

	/*!
	* \brief Destroys a component by index
	*
	* \param index Index of the component
	*
	* \remark If component is not available, no action is performed
	*/

	void Entity::DestroyComponent(ComponentIndex index)
	{
		if (HasComponent(index))
		{
			// We get the component and we alert existing components of the deleted one
			BaseComponent& component = *m_components[index].get();
			for (std::size_t i = m_componentBits.FindFirst(); i != m_componentBits.npos; i = m_componentBits.FindNext(i))
			{
				if (i != index)
					m_components[i]->OnComponentDetached(component);
			}

			component.SetEntity(nullptr);

			m_components[index].reset();
			m_componentBits.Reset(index);
		}
	}

}
<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: xmlDataSource.cxx,v $
 *
 *  $Revision: 1.11 $
 *
 *  last change: $Author: rt $ $Date: 2007-11-09 08:14:00 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 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
 *
 ************************************************************************/

// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_dbaccess.hxx"
#ifndef DBA_XMLDATASOURCE_HXX
#include "xmlDataSource.hxx"
#endif
#ifndef DBA_XMLLOGIN_HXX
#include "xmlLogin.hxx"
#endif
#ifndef DBA_XMLTABLEFILTERLIST_HXX
#include "xmlTableFilterList.hxx"
#endif
#ifndef DBA_XMLDATASOURCEINFO_HXX
#include "xmlDataSourceInfo.hxx"
#endif
#ifndef DBA_XMLDATASOURCESETTINGS_HXX
#include "xmlDataSourceSettings.hxx"
#endif
#ifndef DBA_XMLDATASOURCESETTING_HXX
#include "xmlDataSourceSetting.hxx"
#endif
#ifndef DBA_XMLFILTER_HXX
#include "xmlfilter.hxx"
#endif
#ifndef _XMLOFF_XMLTOKEN_HXX
#include <xmloff/xmltoken.hxx>
#endif
#ifndef _XMLOFF_XMLNMSPE_HXX
#include <xmloff/xmlnmspe.hxx>
#endif
#ifndef _XMLOFF_NMSPMAP_HXX
#include <xmloff/nmspmap.hxx>
#endif
#ifndef DBA_XMLENUMS_HXX
#include "xmlEnums.hxx"
#endif
#ifndef DBACCESS_SHARED_XMLSTRINGS_HRC
#include "xmlstrings.hrc"
#endif
#ifndef _TOOLS_DEBUG_HXX
#include <tools/debug.hxx>
#endif
#ifndef TOOLS_DIAGNOSE_EX_H
#include <tools/diagnose_ex.h>
#endif
#include "xmlConnectionData.hxx"
#include "xmlJavaClassPath.hxx"
namespace dbaxml
{
    using namespace ::com::sun::star::uno;
    using namespace ::com::sun::star::xml::sax;
DBG_NAME(OXMLDataSource)

OXMLDataSource::OXMLDataSource( ODBFilter& rImport,
                sal_uInt16 nPrfx, const ::rtl::OUString& _sLocalName,
                const Reference< XAttributeList > & _xAttrList,bool _bAsDataSource ) :
    SvXMLImportContext( rImport, nPrfx, _sLocalName )
    ,m_bAsDataSource(_bAsDataSource)
{
    DBG_CTOR(OXMLDataSource,NULL);

    OSL_ENSURE(_xAttrList.is(),"Attribute list is NULL!");
    const SvXMLNamespaceMap& rMap = rImport.GetNamespaceMap();
    const SvXMLTokenMap& rTokenMap = rImport.GetDataSourceElemTokenMap();

    Reference<XPropertySet> xDataSource = rImport.getDataSource();

    PropertyValue aProperty;
    bool bParameter_name_substitution = false;
    bool bFoundTableNameLengthLimited = false;
    bool bFoundAppendTableAliasName = false;
    bool bFoundSuppressVersionColumns = false;

    const sal_Int16 nLength = (xDataSource.is() && _xAttrList.is()) ? _xAttrList->getLength() : 0;
    static const ::rtl::OUString s_sTRUE = ::xmloff::token::GetXMLToken(XML_TRUE);
    for(sal_Int16 i = 0; i < nLength; ++i)
    {
        ::rtl::OUString sLocalName;
        rtl::OUString sAttrName = _xAttrList->getNameByIndex( i );
        sal_uInt16 nPrefix = rMap.GetKeyByAttrName( sAttrName,&sLocalName );
        rtl::OUString sValue = _xAttrList->getValueByIndex( i );

        aProperty.Name = ::rtl::OUString();
        aProperty.Value = Any();

        switch( rTokenMap.Get( nPrefix, sLocalName ) )
        {
            case XML_TOK_CONNECTION_RESOURCE:
                try
                {
                    xDataSource->setPropertyValue(PROPERTY_URL,makeAny(sValue));
                }
                catch(Exception)
                {
                    DBG_UNHANDLED_EXCEPTION();
                }
                break;
            case XML_TOK_SUPPRESS_VERSION_COLUMNS:
                try
                {
                    xDataSource->setPropertyValue(PROPERTY_SUPPRESSVERSIONCL,makeAny(sValue == s_sTRUE ? sal_True : sal_False));
                    bFoundSuppressVersionColumns = true;
                }
                catch(Exception)
                {
                    DBG_UNHANDLED_EXCEPTION();
                }
                break;
            case XML_TOK_JAVA_DRIVER_CLASS:
                aProperty.Name = INFO_JDBCDRIVERCLASS;
                break;
            case XML_TOK_EXTENSION:
                aProperty.Name = INFO_TEXTFILEEXTENSION;
                break;
            case XML_TOK_IS_FIRST_ROW_HEADER_LINE:
                aProperty.Name = INFO_TEXTFILEHEADER;
                aProperty.Value <<= (sValue == s_sTRUE ? sal_True : sal_False);
                break;
            case XML_TOK_SHOW_DELETED:
                aProperty.Name = INFO_SHOWDELETEDROWS;
                aProperty.Value <<= (sValue == s_sTRUE ? sal_True : sal_False);
                break;
            case XML_TOK_IS_TABLE_NAME_LENGTH_LIMITED:
                aProperty.Name = INFO_ALLOWLONGTABLENAMES;
                aProperty.Value <<= (sValue == s_sTRUE ? sal_True : sal_False);
                bFoundTableNameLengthLimited = true;
                break;
            case XML_TOK_SYSTEM_DRIVER_SETTINGS:
                aProperty.Name = INFO_ADDITIONALOPTIONS;
                break;
            case XML_TOK_ENABLE_SQL92_CHECK:
                aProperty.Name = PROPERTY_ENABLESQL92CHECK;
                aProperty.Value <<= (sValue == s_sTRUE ? sal_True : sal_False);
                break;
            case XML_TOK_APPEND_TABLE_ALIAS_NAME:
                aProperty.Name = INFO_APPEND_TABLE_ALIAS;
                aProperty.Value <<= (sValue == s_sTRUE ? sal_True : sal_False);
                bFoundAppendTableAliasName = true;
                break;
            case XML_TOK_PARAMETER_NAME_SUBSTITUTION:
                aProperty.Name = INFO_PARAMETERNAMESUBST;
                aProperty.Value <<= (sValue == s_sTRUE ? sal_True : sal_False);
                bParameter_name_substitution = true;
                break;
            case XML_TOK_IGNORE_DRIVER_PRIVILEGES:
                aProperty.Name = INFO_IGNOREDRIVER_PRIV;
                aProperty.Value <<= (sValue == s_sTRUE ? sal_True : sal_False);
                break;
            case XML_TOK_BOOLEAN_COMPARISON_MODE:
                aProperty.Name = PROPERTY_BOOLEANCOMPARISONMODE;
                if ( sValue.equalsAscii("equal-integer") )
                    aProperty.Value <<= sal_Int32(0);
                else if ( sValue.equalsAscii("is-boolean") )
                    aProperty.Value <<= sal_Int32(1);
                else if ( sValue.equalsAscii("equal-boolean") )
                    aProperty.Value <<= sal_Int32(2);
                else if ( sValue.equalsAscii("equal-use-only-zero") )
                    aProperty.Value <<= sal_Int32(3);
                break;
            case XML_TOK_USE_CATALOG:
                aProperty.Name = INFO_USECATALOG;
                aProperty.Value <<= (sValue == s_sTRUE ? sal_True : sal_False);
                break;
            case XML_TOK_BASE_DN:
                aProperty.Name = INFO_CONN_LDAP_BASEDN;
                break;
            case XML_TOK_MAX_ROW_COUNT:
                aProperty.Name = INFO_CONN_LDAP_ROWCOUNT;
                aProperty.Value <<= sValue.toInt32();
                break;
        }
        if ( aProperty.Name.getLength() )
        {
            if ( !aProperty.Value.hasValue() )
                aProperty.Value <<= sValue;
            rImport.addInfo(aProperty);
        }
    }
    if ( rImport.isNewFormat() )
    {
        if ( !bFoundTableNameLengthLimited )
        {
            aProperty.Name = INFO_ALLOWLONGTABLENAMES;
            aProperty.Value <<= sal_True;
            rImport.addInfo(aProperty);
        }
        if ( !bParameter_name_substitution )
        {
            aProperty.Name = INFO_PARAMETERNAMESUBST;
            aProperty.Value <<= sal_True;
            rImport.addInfo(aProperty);
        }
        if ( !bFoundAppendTableAliasName )
        {
            aProperty.Name = INFO_APPEND_TABLE_ALIAS;
            aProperty.Value <<= sal_True;
            rImport.addInfo(aProperty);
        }
        if ( !bFoundSuppressVersionColumns )
        {
            try
            {
                xDataSource->setPropertyValue(PROPERTY_SUPPRESSVERSIONCL,makeAny(sal_True));
            }
            catch(Exception)
            {
                DBG_UNHANDLED_EXCEPTION();
            }
        }
    }
}
// -----------------------------------------------------------------------------

OXMLDataSource::~OXMLDataSource()
{

    DBG_DTOR(OXMLDataSource,NULL);
}
// -----------------------------------------------------------------------------

SvXMLImportContext* OXMLDataSource::CreateChildContext(
        sal_uInt16 nPrefix,
        const ::rtl::OUString& rLocalName,
        const Reference< XAttributeList > & xAttrList )
{
    SvXMLImportContext *pContext = 0;
    const SvXMLTokenMap&    rTokenMap   = GetOwnImport().GetDataSourceElemTokenMap();

    switch( rTokenMap.Get( nPrefix, rLocalName ) )
    {
        case XML_TOK_LOGIN:
            GetOwnImport().GetProgressBarHelper()->Increment( PROGRESS_BAR_STEP );
            pContext = new OXMLLogin( GetOwnImport(), nPrefix, rLocalName,xAttrList );
            break;

        case XML_TOK_TABLE_FILTER:
        case XML_TOK_TABLE_TYPE_FILTER:
            GetOwnImport().GetProgressBarHelper()->Increment( PROGRESS_BAR_STEP );
            pContext = new OXMLTableFilterList( GetImport(), nPrefix, rLocalName );
            break;
        case XML_TOK_AUTO_INCREMENT:
        case XML_TOK_DELIMITER:
        case XML_TOK_FONT_CHARSET:
        case XML_TOK_CHARACTER_SET:
            GetOwnImport().GetProgressBarHelper()->Increment( PROGRESS_BAR_STEP );
            pContext = new OXMLDataSourceInfo( GetOwnImport(), nPrefix, rLocalName,xAttrList);
            break;
        case XML_TOK_DATA_SOURCE_SETTINGS:
            GetOwnImport().GetProgressBarHelper()->Increment( PROGRESS_BAR_STEP );
            pContext = new OXMLDataSourceSettings( GetOwnImport(), nPrefix, rLocalName);
            break;
        case XML_TOK_CONNECTION_DATA:
            GetOwnImport().GetProgressBarHelper()->Increment( PROGRESS_BAR_STEP );
            pContext = new OXMLConnectionData( GetOwnImport(), nPrefix, rLocalName);
            break;
        case XML_TOK_DRIVER_SETTINGS:
            GetOwnImport().GetProgressBarHelper()->Increment( PROGRESS_BAR_STEP );
            pContext = new OXMLDataSource( GetOwnImport(), nPrefix, rLocalName, xAttrList,false);
            break;
        case XML_TOK_JAVA_CLASSPATH:
            GetOwnImport().GetProgressBarHelper()->Increment( PROGRESS_BAR_STEP );
            pContext = new OXMLJavaClassPath( GetOwnImport(), nPrefix, rLocalName,xAttrList );
            break;
        case XML_TOK_APPLICATION_CONNECTION_SETTINGS:
            GetOwnImport().GetProgressBarHelper()->Increment( PROGRESS_BAR_STEP );
            pContext = new OXMLDataSource( GetOwnImport(), nPrefix, rLocalName, xAttrList,false);
            break;
    }

    if( !pContext )
        pContext = new SvXMLImportContext( GetImport(), nPrefix, rLocalName );

    return pContext;
}
// -----------------------------------------------------------------------------
ODBFilter& OXMLDataSource::GetOwnImport()
{
    return static_cast<ODBFilter&>(GetImport());
}
// -----------------------------------------------------------------------------

//----------------------------------------------------------------------------
} // namespace dbaxml
// -----------------------------------------------------------------------------
<commit_msg>INTEGRATION: CWS changefileheader (1.11.84); FILE MERGED 2008/03/31 13:26:54 rt 1.11.84.1: #i87441# Change license header to LPGL v3.<commit_after>/*************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2008 by Sun Microsystems, Inc.
 *
 * OpenOffice.org - a multi-platform office productivity suite
 *
 * $RCSfile: xmlDataSource.cxx,v $
 * $Revision: 1.12 $
 *
 * This file is part of OpenOffice.org.
 *
 * OpenOffice.org is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License version 3
 * only, as published by the Free Software Foundation.
 *
 * OpenOffice.org 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 version 3 for more details
 * (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU Lesser General Public License
 * version 3 along with OpenOffice.org.  If not, see
 * <http://www.openoffice.org/license.html>
 * for a copy of the LGPLv3 License.
 *
 ************************************************************************/

// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_dbaccess.hxx"
#ifndef DBA_XMLDATASOURCE_HXX
#include "xmlDataSource.hxx"
#endif
#ifndef DBA_XMLLOGIN_HXX
#include "xmlLogin.hxx"
#endif
#ifndef DBA_XMLTABLEFILTERLIST_HXX
#include "xmlTableFilterList.hxx"
#endif
#ifndef DBA_XMLDATASOURCEINFO_HXX
#include "xmlDataSourceInfo.hxx"
#endif
#ifndef DBA_XMLDATASOURCESETTINGS_HXX
#include "xmlDataSourceSettings.hxx"
#endif
#ifndef DBA_XMLDATASOURCESETTING_HXX
#include "xmlDataSourceSetting.hxx"
#endif
#ifndef DBA_XMLFILTER_HXX
#include "xmlfilter.hxx"
#endif
#ifndef _XMLOFF_XMLTOKEN_HXX
#include <xmloff/xmltoken.hxx>
#endif
#ifndef _XMLOFF_XMLNMSPE_HXX
#include <xmloff/xmlnmspe.hxx>
#endif
#ifndef _XMLOFF_NMSPMAP_HXX
#include <xmloff/nmspmap.hxx>
#endif
#ifndef DBA_XMLENUMS_HXX
#include "xmlEnums.hxx"
#endif
#ifndef DBACCESS_SHARED_XMLSTRINGS_HRC
#include "xmlstrings.hrc"
#endif
#ifndef _TOOLS_DEBUG_HXX
#include <tools/debug.hxx>
#endif
#ifndef TOOLS_DIAGNOSE_EX_H
#include <tools/diagnose_ex.h>
#endif
#include "xmlConnectionData.hxx"
#include "xmlJavaClassPath.hxx"
namespace dbaxml
{
    using namespace ::com::sun::star::uno;
    using namespace ::com::sun::star::xml::sax;
DBG_NAME(OXMLDataSource)

OXMLDataSource::OXMLDataSource( ODBFilter& rImport,
                sal_uInt16 nPrfx, const ::rtl::OUString& _sLocalName,
                const Reference< XAttributeList > & _xAttrList,bool _bAsDataSource ) :
    SvXMLImportContext( rImport, nPrfx, _sLocalName )
    ,m_bAsDataSource(_bAsDataSource)
{
    DBG_CTOR(OXMLDataSource,NULL);

    OSL_ENSURE(_xAttrList.is(),"Attribute list is NULL!");
    const SvXMLNamespaceMap& rMap = rImport.GetNamespaceMap();
    const SvXMLTokenMap& rTokenMap = rImport.GetDataSourceElemTokenMap();

    Reference<XPropertySet> xDataSource = rImport.getDataSource();

    PropertyValue aProperty;
    bool bParameter_name_substitution = false;
    bool bFoundTableNameLengthLimited = false;
    bool bFoundAppendTableAliasName = false;
    bool bFoundSuppressVersionColumns = false;

    const sal_Int16 nLength = (xDataSource.is() && _xAttrList.is()) ? _xAttrList->getLength() : 0;
    static const ::rtl::OUString s_sTRUE = ::xmloff::token::GetXMLToken(XML_TRUE);
    for(sal_Int16 i = 0; i < nLength; ++i)
    {
        ::rtl::OUString sLocalName;
        rtl::OUString sAttrName = _xAttrList->getNameByIndex( i );
        sal_uInt16 nPrefix = rMap.GetKeyByAttrName( sAttrName,&sLocalName );
        rtl::OUString sValue = _xAttrList->getValueByIndex( i );

        aProperty.Name = ::rtl::OUString();
        aProperty.Value = Any();

        switch( rTokenMap.Get( nPrefix, sLocalName ) )
        {
            case XML_TOK_CONNECTION_RESOURCE:
                try
                {
                    xDataSource->setPropertyValue(PROPERTY_URL,makeAny(sValue));
                }
                catch(Exception)
                {
                    DBG_UNHANDLED_EXCEPTION();
                }
                break;
            case XML_TOK_SUPPRESS_VERSION_COLUMNS:
                try
                {
                    xDataSource->setPropertyValue(PROPERTY_SUPPRESSVERSIONCL,makeAny(sValue == s_sTRUE ? sal_True : sal_False));
                    bFoundSuppressVersionColumns = true;
                }
                catch(Exception)
                {
                    DBG_UNHANDLED_EXCEPTION();
                }
                break;
            case XML_TOK_JAVA_DRIVER_CLASS:
                aProperty.Name = INFO_JDBCDRIVERCLASS;
                break;
            case XML_TOK_EXTENSION:
                aProperty.Name = INFO_TEXTFILEEXTENSION;
                break;
            case XML_TOK_IS_FIRST_ROW_HEADER_LINE:
                aProperty.Name = INFO_TEXTFILEHEADER;
                aProperty.Value <<= (sValue == s_sTRUE ? sal_True : sal_False);
                break;
            case XML_TOK_SHOW_DELETED:
                aProperty.Name = INFO_SHOWDELETEDROWS;
                aProperty.Value <<= (sValue == s_sTRUE ? sal_True : sal_False);
                break;
            case XML_TOK_IS_TABLE_NAME_LENGTH_LIMITED:
                aProperty.Name = INFO_ALLOWLONGTABLENAMES;
                aProperty.Value <<= (sValue == s_sTRUE ? sal_True : sal_False);
                bFoundTableNameLengthLimited = true;
                break;
            case XML_TOK_SYSTEM_DRIVER_SETTINGS:
                aProperty.Name = INFO_ADDITIONALOPTIONS;
                break;
            case XML_TOK_ENABLE_SQL92_CHECK:
                aProperty.Name = PROPERTY_ENABLESQL92CHECK;
                aProperty.Value <<= (sValue == s_sTRUE ? sal_True : sal_False);
                break;
            case XML_TOK_APPEND_TABLE_ALIAS_NAME:
                aProperty.Name = INFO_APPEND_TABLE_ALIAS;
                aProperty.Value <<= (sValue == s_sTRUE ? sal_True : sal_False);
                bFoundAppendTableAliasName = true;
                break;
            case XML_TOK_PARAMETER_NAME_SUBSTITUTION:
                aProperty.Name = INFO_PARAMETERNAMESUBST;
                aProperty.Value <<= (sValue == s_sTRUE ? sal_True : sal_False);
                bParameter_name_substitution = true;
                break;
            case XML_TOK_IGNORE_DRIVER_PRIVILEGES:
                aProperty.Name = INFO_IGNOREDRIVER_PRIV;
                aProperty.Value <<= (sValue == s_sTRUE ? sal_True : sal_False);
                break;
            case XML_TOK_BOOLEAN_COMPARISON_MODE:
                aProperty.Name = PROPERTY_BOOLEANCOMPARISONMODE;
                if ( sValue.equalsAscii("equal-integer") )
                    aProperty.Value <<= sal_Int32(0);
                else if ( sValue.equalsAscii("is-boolean") )
                    aProperty.Value <<= sal_Int32(1);
                else if ( sValue.equalsAscii("equal-boolean") )
                    aProperty.Value <<= sal_Int32(2);
                else if ( sValue.equalsAscii("equal-use-only-zero") )
                    aProperty.Value <<= sal_Int32(3);
                break;
            case XML_TOK_USE_CATALOG:
                aProperty.Name = INFO_USECATALOG;
                aProperty.Value <<= (sValue == s_sTRUE ? sal_True : sal_False);
                break;
            case XML_TOK_BASE_DN:
                aProperty.Name = INFO_CONN_LDAP_BASEDN;
                break;
            case XML_TOK_MAX_ROW_COUNT:
                aProperty.Name = INFO_CONN_LDAP_ROWCOUNT;
                aProperty.Value <<= sValue.toInt32();
                break;
        }
        if ( aProperty.Name.getLength() )
        {
            if ( !aProperty.Value.hasValue() )
                aProperty.Value <<= sValue;
            rImport.addInfo(aProperty);
        }
    }
    if ( rImport.isNewFormat() )
    {
        if ( !bFoundTableNameLengthLimited )
        {
            aProperty.Name = INFO_ALLOWLONGTABLENAMES;
            aProperty.Value <<= sal_True;
            rImport.addInfo(aProperty);
        }
        if ( !bParameter_name_substitution )
        {
            aProperty.Name = INFO_PARAMETERNAMESUBST;
            aProperty.Value <<= sal_True;
            rImport.addInfo(aProperty);
        }
        if ( !bFoundAppendTableAliasName )
        {
            aProperty.Name = INFO_APPEND_TABLE_ALIAS;
            aProperty.Value <<= sal_True;
            rImport.addInfo(aProperty);
        }
        if ( !bFoundSuppressVersionColumns )
        {
            try
            {
                xDataSource->setPropertyValue(PROPERTY_SUPPRESSVERSIONCL,makeAny(sal_True));
            }
            catch(Exception)
            {
                DBG_UNHANDLED_EXCEPTION();
            }
        }
    }
}
// -----------------------------------------------------------------------------

OXMLDataSource::~OXMLDataSource()
{

    DBG_DTOR(OXMLDataSource,NULL);
}
// -----------------------------------------------------------------------------

SvXMLImportContext* OXMLDataSource::CreateChildContext(
        sal_uInt16 nPrefix,
        const ::rtl::OUString& rLocalName,
        const Reference< XAttributeList > & xAttrList )
{
    SvXMLImportContext *pContext = 0;
    const SvXMLTokenMap&    rTokenMap   = GetOwnImport().GetDataSourceElemTokenMap();

    switch( rTokenMap.Get( nPrefix, rLocalName ) )
    {
        case XML_TOK_LOGIN:
            GetOwnImport().GetProgressBarHelper()->Increment( PROGRESS_BAR_STEP );
            pContext = new OXMLLogin( GetOwnImport(), nPrefix, rLocalName,xAttrList );
            break;

        case XML_TOK_TABLE_FILTER:
        case XML_TOK_TABLE_TYPE_FILTER:
            GetOwnImport().GetProgressBarHelper()->Increment( PROGRESS_BAR_STEP );
            pContext = new OXMLTableFilterList( GetImport(), nPrefix, rLocalName );
            break;
        case XML_TOK_AUTO_INCREMENT:
        case XML_TOK_DELIMITER:
        case XML_TOK_FONT_CHARSET:
        case XML_TOK_CHARACTER_SET:
            GetOwnImport().GetProgressBarHelper()->Increment( PROGRESS_BAR_STEP );
            pContext = new OXMLDataSourceInfo( GetOwnImport(), nPrefix, rLocalName,xAttrList);
            break;
        case XML_TOK_DATA_SOURCE_SETTINGS:
            GetOwnImport().GetProgressBarHelper()->Increment( PROGRESS_BAR_STEP );
            pContext = new OXMLDataSourceSettings( GetOwnImport(), nPrefix, rLocalName);
            break;
        case XML_TOK_CONNECTION_DATA:
            GetOwnImport().GetProgressBarHelper()->Increment( PROGRESS_BAR_STEP );
            pContext = new OXMLConnectionData( GetOwnImport(), nPrefix, rLocalName);
            break;
        case XML_TOK_DRIVER_SETTINGS:
            GetOwnImport().GetProgressBarHelper()->Increment( PROGRESS_BAR_STEP );
            pContext = new OXMLDataSource( GetOwnImport(), nPrefix, rLocalName, xAttrList,false);
            break;
        case XML_TOK_JAVA_CLASSPATH:
            GetOwnImport().GetProgressBarHelper()->Increment( PROGRESS_BAR_STEP );
            pContext = new OXMLJavaClassPath( GetOwnImport(), nPrefix, rLocalName,xAttrList );
            break;
        case XML_TOK_APPLICATION_CONNECTION_SETTINGS:
            GetOwnImport().GetProgressBarHelper()->Increment( PROGRESS_BAR_STEP );
            pContext = new OXMLDataSource( GetOwnImport(), nPrefix, rLocalName, xAttrList,false);
            break;
    }

    if( !pContext )
        pContext = new SvXMLImportContext( GetImport(), nPrefix, rLocalName );

    return pContext;
}
// -----------------------------------------------------------------------------
ODBFilter& OXMLDataSource::GetOwnImport()
{
    return static_cast<ODBFilter&>(GetImport());
}
// -----------------------------------------------------------------------------

//----------------------------------------------------------------------------
} // namespace dbaxml
// -----------------------------------------------------------------------------
<|endoftext|>


<commit_before>// %llvmgcc %s -S -o -
namespace std {
  class exception { };

  class type_info {
  public:
    virtual ~type_info();
  };

}

namespace __cxxabiv1 {
  class __si_class_type_info : public std::type_info {
    ~__si_class_type_info();
  };
}

class recursive_init: public std::exception {
public:
  virtual ~recursive_init() throw ();
};

recursive_init::~recursive_init() throw() { }

<commit_msg>Add a RUN: line so this test doesn't fail.<commit_after>// RUN: %llvmgcc %s -S -o -
namespace std {
  class exception { };

  class type_info {
  public:
    virtual ~type_info();
  };

}

namespace __cxxabiv1 {
  class __si_class_type_info : public std::type_info {
    ~__si_class_type_info();
  };
}

class recursive_init: public std::exception {
public:
  virtual ~recursive_init() throw ();
};

recursive_init::~recursive_init() throw() { }

<|endoftext|>


<commit_before>//
// Create bar charts of frequency of letters.
//
#include "vtk.h"
#include <stdio.h>
#include <ctype.h>

main (int argc, char *argv[])
{
  vtkVectorText *letters[26];
  vtkLinearExtrusionFilter *extrude[26];
  vtkPolyDataMapper *mappers[26];
  vtkActor *actors[26];
  char text[2];
  static char alphabet[]="ABCDEFGHIJKLMNOPQRSTUVWXYZ";
  int i, j, freq[26], maxFreq;
  float x, y;
  FILE *fPtr;
  int c;
//
// count the letters
//
  if ( argc < 2 )
    {
    cerr << "Please provide filename: " << argv[0] << " filename\n";
    exit(1);
    }

  if ( (fPtr = fopen (argv[1], "r")) == NULL )
    {
    cerr << "Cannot open file: " <<  argv[1] << "\n";
    exit(1);
    }

  for (i=0; i<26; i++) freq[i] = 0;
  while ( (c=fgetc(fPtr)) != EOF )
    {
    if ( isalpha(c) )
      {
      c = tolower(c);
      freq[c-97]++;
      }
    }

  for (maxFreq=0, i=0; i<26; i++)
    if ( freq[i] > maxFreq )
      maxFreq = freq[i];
//
// graphics stuff
//
  vtkRenderer *ren = vtkRenderer::New();
  vtkRenderWindow *renWin = vtkRenderWindow::New();
    renWin->AddRenderer(ren);
  vtkRenderWindowInteractor *iren = vtkRenderWindowInteractor::New();
    iren->SetRenderWindow(renWin);
//
// Setup letters
//
  text[1] = '\0';
  for (i=0; i<26; i++)
    {
    text[0] = alphabet[i];
    letters[i] = vtkVectorText::New();
      letters[i]->SetText(text);
    extrude[i] = vtkLinearExtrusionFilter::New();
      extrude[i]->SetInput(letters[i]->GetOutput());
      extrude[i]->SetExtrusionType(VTK_VECTOR_EXTRUSION);
      extrude[i]->SetVector(0,0,1.0);
      extrude[i]->SetScaleFactor((float)freq[i] / maxFreq * 2.50);
    mappers[i] = vtkPolyDataMapper::New();
      mappers[i]->SetInput(extrude[i]->GetOutput());
      mappers[i]->ScalarVisibilityOff();
    actors[i] = vtkActor::New();
      actors[i]->SetMapper(mappers[i]);
      actors[i]->GetProperty()->SetColor(0.2000, 0.6300, 0.7900);
      if ( freq[i] <= 0 ) actors[i]->VisibilityOff();
    ren->AddActor(actors[i]);
    }
//
// Position actors
//
  for (y=0.0, j=0; j<2; j++, y+=(-2.0))
    for (x=0.0, i=0; i<13; i++, x+=1.0)
      actors[j*13 + i]->SetPosition(x, y, 0.0);

  ren->SetBackground(1,1,1);
  renWin->SetSize(1250,750);
  renWin->Render();

  // interact with data
  iren->Start();

  // Clean up
  ren->Delete();
  renWin->Delete();
  iren->Delete();
  for (i=0; i<26; i++)
    {
    letters[i]->Delete();
    extrude[i]->Delete();
    mappers[i]->Delete();
    actors[i]->Delete();
    }
}
<commit_msg>Improved letter placement<commit_after>//
// Create bar charts of frequency of letters.
//
#include "vtk.h"
#include <stdio.h>
#include <ctype.h>

main (int argc, char *argv[])
{
  vtkVectorText *letters[26];
  vtkLinearExtrusionFilter *extrude[26];
  vtkPolyDataMapper *mappers[26];
  vtkActor *actors[26];
  char text[2];
  static char alphabet[]="ABCDEFGHIJKLMNOPQRSTUVWXYZ";
  int i, j, freq[26], maxFreq;
  float x, y;
  FILE *fPtr;
  int c;
//
// count the letters
//
  if ( argc < 2 )
    {
    cerr << "Please provide filename: " << argv[0] << " filename\n";
    exit(1);
    }

  if ( (fPtr = fopen (argv[1], "r")) == NULL )
    {
    cerr << "Cannot open file: " <<  argv[1] << "\n";
    exit(1);
    }

  for (i=0; i<26; i++) freq[i] = 0;
  while ( (c=fgetc(fPtr)) != EOF )
    {
    if ( isalpha(c) )
      {
      c = tolower(c);
      freq[c-97]++;
      }
    }

  for (maxFreq=0, i=0; i<26; i++)
    if ( freq[i] > maxFreq )
      maxFreq = freq[i];
//
// graphics stuff
//
  vtkRenderer *ren = vtkRenderer::New();
  vtkRenderWindow *renWin = vtkRenderWindow::New();
    renWin->AddRenderer(ren);
  vtkRenderWindowInteractor *iren = vtkRenderWindowInteractor::New();
    iren->SetRenderWindow(renWin);
//
// Setup letters
//
  text[1] = '\0';
  for (i=0; i<26; i++)
    {
    text[0] = alphabet[i];
    letters[i] = vtkVectorText::New();
      letters[i]->SetText(text);
    extrude[i] = vtkLinearExtrusionFilter::New();
      extrude[i]->SetInput(letters[i]->GetOutput());
      extrude[i]->SetExtrusionType(VTK_VECTOR_EXTRUSION);
      extrude[i]->SetVector(0,0,1.0);
      extrude[i]->SetScaleFactor((float)freq[i] / maxFreq * 2.50);
    mappers[i] = vtkPolyDataMapper::New();
      mappers[i]->SetInput(extrude[i]->GetOutput());
      mappers[i]->ScalarVisibilityOff();
    actors[i] = vtkActor::New();
      actors[i]->SetMapper(mappers[i]);
      actors[i]->GetProperty()->SetColor(0.2000, 0.6300, 0.7900);
      if ( freq[i] <= 0 ) actors[i]->VisibilityOff();
    ren->AddActor(actors[i]);
    }
//
// Position actors
//
  for (y=0.0, j=0; j<2; j++, y+=(-3.0))
    for (x=0.0, i=0; i<13; i++, x+=1.5)
      actors[j*13 + i]->SetPosition(x, y, 0.0);

  ren->SetBackground(1,1,1);
  renWin->SetSize(1250,500);
  renWin->Render();

  // interact with data
  iren->Start();

  // Clean up
  ren->Delete();
  renWin->Delete();
  iren->Delete();
  for (i=0; i<26; i++)
    {
    letters[i]->Delete();
    extrude[i]->Delete();
    mappers[i]->Delete();
    actors[i]->Delete();
    }
}
<|endoftext|>