<commit_before>#include <stdio.h>
#include "Halide.h"
using namespace Halide;

int main(int argc, char **argv) {

    Func f, g, h; Var x, y;

    h(x) = x;
    g(x) = h(x-1) + h(x+1);
    f(x, y) = (g(x-1) + g(x+1)) + y;

    h.compute_root();
    g.compute_root();

    Target target = get_jit_target_from_environment();
    if (target.has_gpu_feature()) {
        f.gpu_tile(x, y, 16, 16);
        g.gpu_tile(x, 128);
        h.gpu_tile(x, 128);
    }

    Image<int> out = f.realize(32, 32, target);

    for (int y = 0; y < 32; y++) {
        for (int x = 0; x < 32; x++) {
            if (out(x, y) != x*4 + y) {
                printf("out(%d, %d) = %d instead of %d\n", x, y, out(x, y), x*4+y);
                return -1;
            }
        }
    }

    printf("Success!\n");
    return 0;
}
<commit_msg>Added hexagon scheduling directives.<commit_after>#include <stdio.h>
#include "Halide.h"
using namespace Halide;

int main(int argc, char **argv) {

    Func f, g, h; Var x, y;

    h(x) = x;
    g(x) = h(x-1) + h(x+1);
    f(x, y) = (g(x-1) + g(x+1)) + y;

    h.compute_root();
    g.compute_root();

    Target target = get_jit_target_from_environment();
    if (target.has_gpu_feature()) {
        f.gpu_tile(x, y, 16, 16);
        g.gpu_tile(x, 128);
        h.gpu_tile(x, 128);
    } else if (target.features_any_of({Target::HVX_64, Target::HVX_128})) {
        f.hexagon().vectorize(x, 32);
        g.hexagon().vectorize(x, 32);
        h.hexagon().vectorize(x, 32);
    }

    Image<int> out = f.realize(32, 32, target);

    for (int y = 0; y < 32; y++) {
        for (int x = 0; x < 32; x++) {
            if (out(x, y) != x*4 + y) {
                printf("out(%d, %d) = %d instead of %d\n", x, y, out(x, y), x*4+y);
                return -1;
            }
        }
    }

    printf("Success!\n");
    return 0;
}
<|endoftext|>


<commit_before>#ifndef DICT_HPP
#define DICT_HPP

#include <string>
#include <vector>
#include <stdexcept>
#include <tuple>
#include <cmath>
#include <functional>

#include <boost/iterator/iterator_facade.hpp>

#include "detail/prime.hpp"
#include "detail/key_value.hpp"
#include "detail/iterator.hpp"

namespace boost {

// container
template <typename Key, typename Value, typename Hasher = std::hash<Key>,
          typename KeyEqual = std::equal_to<Key>,
          typename Allocator =
              std::allocator<std::tuple<bool, detail::key_value<Key, Value>>>>
class dict {
public:
    typedef Key key_type;
    typedef Value mapped_type;
    typedef Allocator allocator_type;
    typedef Hasher hasher;
    typedef KeyEqual key_equal;

    typedef std::pair<const Key, Value> value_type;
    typedef std::tuple<bool, detail::key_value<Key, Value>> entry_type;
    typedef std::vector<entry_type, allocator_type> table_type;
    typedef typename table_type::size_type size_type;
    typedef typename table_type::difference_type difference_type;
    typedef value_type& reference;

    typedef detail::dict_iterator<Key, Value> iterator;
    typedef detail::const_dict_iterator<Key, Value> const_iterator;

    dict()
        : _table(initial_size()), _element_count(0),
          _max_element_count(initial_load_factor() * _table.size()) {}

    iterator begin() noexcept {
        return { _table.begin(), _table.end() };
    }

    const_iterator begin() const noexcept {
        return { _table.begin(), _table.end() };
    }

    const_iterator cbegin() const noexcept {
        return { _table.begin(), _table.end() };
    }

    iterator end() noexcept {
        return { _table.end(), _table.end() };
    }

    const_iterator end() const noexcept {
        return { _table.end(), _table.end() };
    }

    const_iterator cend() const noexcept {
        return { _table.end(), _table.end() };
    }

    size_type size() const noexcept { return _element_count; }

    bool empty() const noexcept { return _element_count == 0; }

    // size_type max_size() const {}

    void clear() {
        _table.clear();
        _element_count = 0;
    }

    template <typename... Args>
    std::pair<iterator, bool> emplace(Args&&... args) {
        auto entry = make_entry(std::forward<Args>(args)...);
        auto index = find_index(std::get<1>(entry).view.first);

        if (std::get<0>(_table[index])) {
            return { { std::next(_table.begin(), index), _table.end() },
                     false };
        } else {
            insert_element(index, std::move(entry));
            return { { std::next(_table.begin(), index), _table.end() }, true };
        }
    }

    template <typename... Args>
    std::pair<iterator, bool> emplace_hint(const_iterator /* hint */, Args&&... args) {
        return emplace(std::forward<Args>(args)...);
    }

    std::pair<iterator, bool> insert(const value_type& obj) {
        auto index = find_index(obj.first);

        if (std::get<0>(_table[index])) {
            return { { std::next(_table.begin(), index), _table.end() },
                     false };
        } else {
            insert_element(index, make_entry(obj.first, obj.second));
            return { { std::next(_table.begin(), index), _table.end() }, true };
        }
    }

    iterator find(const Key& key) {
        auto index = find_index(key);

        if (std::get<0>(_table[index])) {
            return { std::next(_table.begin(), index), _table.end() };
        } else {
            return end();
        }
    }

    const_iterator find(const Key& key) const {
        auto index = find_index(key);

        if (std::get<0>(_table[index])) {
            return { std::next(_table.begin(), index), _table.end() };
        } else {
            return end();
        }
    }

    Value& at(const Key& key) {
        auto index = find_index(key);

        if(std::get<0>(_table[index])) {
            return std::get<1>(_table[index]).view.second;
        }

        throw std::out_of_range("Key not in dict");
    }

    const Value& at(const Key& key) const {
        auto index = find_index(key);

        if(std::get<0>(_table[index])) {
            return std::get<1>(_table[index]).view.second;
        }

        throw std::out_of_range("Key not in dict");
    }

    size_type count(const Key& key) const {
        return find(key) == end() ? 0 : 1;
    }

    std::pair<iterator, iterator> equal_range(const Key& key) {
        return { find(key), end() };
    }

    std::pair<const_iterator, const_iterator> equal_range(const Key& key) const {
        return { find(key), end() };
    }

    Value& operator[](const Key& key) {
        auto index = find_index(key);

        if (std::get<0>(_table[index])) {
            return std::get<1>(_table[index]).view.second;
        } else {
            return insert_element(index, make_entry(key, Value()));
        }
    }

    size_type erase(const Key& key) {
        auto index = find_index(key);

        if (!std::get<0>(_table[index])) {
            return 0;
        }

        auto delete_index = index;

        bool keep = true;
        while (keep) {
            _table[index] = empty_slot_factory();

            while (true) {
                delete_index = (delete_index + 1) % _table.size();

                if (!std::get<0>(_table[delete_index])) {
                    keep = false;
                    break;
                }

                auto new_key =
                    hash_index(std::get<1>(_table[delete_index]).view.first);

                if ((index <= delete_index)
                        ? ((index < new_key) && (new_key <= delete_index))
                        : (new_key <= delete_index)) {
                    continue;
                }

                _table[index] = std::move(_table[delete_index]);
                index = delete_index;
            }
        }

        return 1;
    }

    float load_factor() const { return _element_count / float(_table.size()); }

    float max_load_factor() const {
        return _max_element_count / float(_table.size());
    }

    void max_load_factor(float new_max_load_factor) {
        _max_element_count = std::ceil(new_max_load_factor * _table.size());
        if (check_rehash()) {
            rehash();
        }
    }

    void reserve(std::size_t new_size) {
        if (new_size > _table.size()) {
            auto old_load_factor = max_load_factor();

            table_type new_table(
                next_prime(std::ceil(new_size / old_load_factor)));
            new_table.swap(_table);
            _max_element_count = old_load_factor * _table.size();
            _element_count = 0;

            for (auto&& e : new_table) {
                if (std::get<0>(e)) {
                    (*this)[std::get<1>(e).view.first] =
                        std::move(std::get<1>(e).view.second);
                }
            }
        }
    }

    void rehash() { reserve(2 * _table.size()); }

    bool next_is_rehash() const { return size() + 1 >= _max_element_count; }

private:
    template <typename Entry>
    Value& insert_element(size_type index, Entry&& new_entry) {
        _table[index] = std::forward<Entry>(new_entry);
        ++_element_count;

        if (check_rehash()) {
            rehash();
            index = find_index(std::get<1>(new_entry).view.first);
        }

        return std::get<1>(_table[index]).view.second;
    }

    size_type find_index(const Key& key) const {
        auto index = hash_index(key);

        while (std::get<0>(_table[index])) {
            if (_key_equal(std::get<1>(_table[index]).view.first, key)) {
                return index;
            }

            index = (index + 1) % _table.size();
        }

        return index;
    }

    bool check_rehash() const { return size() >= _max_element_count; }

    size_type hash_index(const Key& key) const {
        return _hasher(key) % _table.size();
    }

    template <typename... Args>
    entry_type make_entry(Args&&... args) const {
        return std::make_tuple(
            true, detail::key_value<Key, Value>(std::forward<Args>(args)...));
    }

    entry_type empty_slot_factory() const {
        return std::make_tuple(false,
                               detail::key_value<Key, Value>(Key(), Value()));
    }

    size_type initial_size() const { return next_prime(8); }

    constexpr float initial_load_factor() const { return 0.7; }

    hasher _hasher;
    key_equal _key_equal;
    table_type _table;
    size_type _element_count;
    size_type _max_element_count;
};

} // namespace boost

#endif
<commit_msg>added key_equal and hash_function<commit_after>#ifndef DICT_HPP
#define DICT_HPP

#include <string>
#include <vector>
#include <stdexcept>
#include <tuple>
#include <cmath>
#include <functional>

#include <boost/iterator/iterator_facade.hpp>

#include "detail/prime.hpp"
#include "detail/key_value.hpp"
#include "detail/iterator.hpp"

namespace boost {

// container
template <typename Key, typename Value, typename Hasher = std::hash<Key>,
          typename KeyEqual = std::equal_to<Key>,
          typename Allocator =
              std::allocator<std::tuple<bool, detail::key_value<Key, Value>>>>
class dict {
public:
    typedef Key key_type;
    typedef Value mapped_type;
    typedef Allocator allocator_type;
    typedef Hasher hasher;
    typedef KeyEqual key_equal;

    typedef std::pair<const Key, Value> value_type;
    typedef std::tuple<bool, detail::key_value<Key, Value>> entry_type;
    typedef std::vector<entry_type, allocator_type> table_type;
    typedef typename table_type::size_type size_type;
    typedef typename table_type::difference_type difference_type;
    typedef value_type& reference;

    typedef detail::dict_iterator<Key, Value> iterator;
    typedef detail::const_dict_iterator<Key, Value> const_iterator;

    dict()
        : _table(initial_size()), _element_count(0),
          _max_element_count(initial_load_factor() * _table.size()) {}

    iterator begin() noexcept {
        return { _table.begin(), _table.end() };
    }

    const_iterator begin() const noexcept {
        return { _table.begin(), _table.end() };
    }

    const_iterator cbegin() const noexcept {
        return { _table.begin(), _table.end() };
    }

    iterator end() noexcept {
        return { _table.end(), _table.end() };
    }

    const_iterator end() const noexcept {
        return { _table.end(), _table.end() };
    }

    const_iterator cend() const noexcept {
        return { _table.end(), _table.end() };
    }

    size_type size() const noexcept { return _element_count; }

    bool empty() const noexcept { return _element_count == 0; }

    // size_type max_size() const {}

    void clear() {
        _table.clear();
        _element_count = 0;
    }

    template <typename... Args>
    std::pair<iterator, bool> emplace(Args&&... args) {
        auto entry = make_entry(std::forward<Args>(args)...);
        auto index = find_index(std::get<1>(entry).view.first);

        if (std::get<0>(_table[index])) {
            return { { std::next(_table.begin(), index), _table.end() },
                     false };
        } else {
            insert_element(index, std::move(entry));
            return { { std::next(_table.begin(), index), _table.end() }, true };
        }
    }

    template <typename... Args>
    std::pair<iterator, bool> emplace_hint(const_iterator /* hint */,
                                           Args&&... args) {
        return emplace(std::forward<Args>(args)...);
    }

    std::pair<iterator, bool> insert(const value_type& obj) {
        auto index = find_index(obj.first);

        if (std::get<0>(_table[index])) {
            return { { std::next(_table.begin(), index), _table.end() },
                     false };
        } else {
            insert_element(index, make_entry(obj.first, obj.second));
            return { { std::next(_table.begin(), index), _table.end() }, true };
        }
    }

    iterator find(const Key& key) {
        auto index = find_index(key);

        if (std::get<0>(_table[index])) {
            return { std::next(_table.begin(), index), _table.end() };
        } else {
            return end();
        }
    }

    const_iterator find(const Key& key) const {
        auto index = find_index(key);

        if (std::get<0>(_table[index])) {
            return { std::next(_table.begin(), index), _table.end() };
        } else {
            return end();
        }
    }

    Value& at(const Key& key) {
        auto index = find_index(key);

        if (std::get<0>(_table[index])) {
            return std::get<1>(_table[index]).view.second;
        }

        throw std::out_of_range("Key not in dict");
    }

    const Value& at(const Key& key) const {
        auto index = find_index(key);

        if (std::get<0>(_table[index])) {
            return std::get<1>(_table[index]).view.second;
        }

        throw std::out_of_range("Key not in dict");
    }

    size_type count(const Key& key) const { return find(key) == end() ? 0 : 1; }

    std::pair<iterator, iterator> equal_range(const Key& key) {
        return { find(key), end() };
    }

    std::pair<const_iterator, const_iterator>
    equal_range(const Key& key) const {
        return { find(key), end() };
    }

    Value& operator[](const Key& key) {
        auto index = find_index(key);

        if (std::get<0>(_table[index])) {
            return std::get<1>(_table[index]).view.second;
        } else {
            return insert_element(index, make_entry(key, Value()));
        }
    }

    size_type erase(const Key& key) {
        auto index = find_index(key);

        if (!std::get<0>(_table[index])) {
            return 0;
        }

        auto delete_index = index;

        bool keep = true;
        while (keep) {
            _table[index] = empty_slot_factory();

            while (true) {
                delete_index = (delete_index + 1) % _table.size();

                if (!std::get<0>(_table[delete_index])) {
                    keep = false;
                    break;
                }

                auto new_key =
                    hash_index(std::get<1>(_table[delete_index]).view.first);

                if ((index <= delete_index)
                        ? ((index < new_key) && (new_key <= delete_index))
                        : (new_key <= delete_index)) {
                    continue;
                }

                _table[index] = std::move(_table[delete_index]);
                index = delete_index;
            }
        }

        return 1;
    }

    float load_factor() const { return _element_count / float(_table.size()); }

    float max_load_factor() const {
        return _max_element_count / float(_table.size());
    }

    void max_load_factor(float new_max_load_factor) {
        _max_element_count = std::ceil(new_max_load_factor * _table.size());
        if (check_rehash()) {
            rehash();
        }
    }

    void reserve(std::size_t new_size) {
        if (new_size > _table.size()) {
            auto old_load_factor = max_load_factor();

            table_type new_table(
                next_prime(std::ceil(new_size / old_load_factor)));
            new_table.swap(_table);
            _max_element_count = old_load_factor * _table.size();
            _element_count = 0;

            for (auto&& e : new_table) {
                if (std::get<0>(e)) {
                    (*this)[std::get<1>(e).view.first] =
                        std::move(std::get<1>(e).view.second);
                }
            }
        }
    }

    void rehash() { reserve(2 * _table.size()); }

    bool next_is_rehash() const { return size() + 1 >= _max_element_count; }

    hasher hash_function() const { return _hasher; }

    key_equal key_eq() const { return _key_equal; }

private:
    template <typename Entry>
    Value& insert_element(size_type index, Entry&& new_entry) {
        _table[index] = std::forward<Entry>(new_entry);
        ++_element_count;

        if (check_rehash()) {
            rehash();
            index = find_index(std::get<1>(new_entry).view.first);
        }

        return std::get<1>(_table[index]).view.second;
    }

    size_type find_index(const Key& key) const {
        auto index = hash_index(key);

        while (std::get<0>(_table[index])) {
            if (_key_equal(std::get<1>(_table[index]).view.first, key)) {
                return index;
            }

            index = (index + 1) % _table.size();
        }

        return index;
    }

    bool check_rehash() const { return size() >= _max_element_count; }

    size_type hash_index(const Key& key) const {
        return _hasher(key) % _table.size();
    }

    template <typename... Args>
    entry_type make_entry(Args&&... args) const {
        return std::make_tuple(
            true, detail::key_value<Key, Value>(std::forward<Args>(args)...));
    }

    entry_type empty_slot_factory() const {
        return std::make_tuple(false,
                               detail::key_value<Key, Value>(Key(), Value()));
    }

    size_type initial_size() const { return next_prime(8); }

    constexpr float initial_load_factor() const { return 0.7; }

    hasher _hasher;
    key_equal _key_equal;
    table_type _table;
    size_type _element_count;
    size_type _max_element_count;
};

} // namespace boost

#endif
<|endoftext|>


<commit_before>// @(#)root/core/meta:$Id$
// Author: Vassil Vassilev   7/10/2012

/*************************************************************************
 * Copyright (C) 1995-2012, Rene Brun and Fons Rademakers.               *
 * All rights reserved.                                                  *
 *                                                                       *
 * For the licensing terms see $ROOTSYS/LICENSE.                         *
 * For the list of contributors see $ROOTSYS/README/CREDITS.             *
 *************************************************************************/

#include "TClingCallbacks.h"

#include "cling/Interpreter/Interpreter.h"
#include "cling/Interpreter/InterpreterCallbacks.h"
#include "cling/Interpreter/Transaction.h"
#include "cling/Utils/AST.h"

#include "clang/AST/ASTContext.h"
#include "clang/AST/DeclBase.h"
#include "clang/Lex/Preprocessor.h"
#include "clang/Parse/Parser.h"
#include "clang/Sema/Lookup.h"
#include "clang/Sema/Scope.h"

using namespace clang;
using namespace cling;

class TObject;

// Functions used to forward calls from code compiled with no-rtti to code
// compiled with rtti.
extern "C" {
   void TCintWithCling__UpdateListsOnCommitted(const cling::Transaction&);
   void TCintWithCling__UpdateListsOnUnloaded(const cling::Transaction&);
   TObject* TCintWithCling__GetObjectAddress(const char *Name, void *&LookupCtx);
   Decl* TCintWithCling__GetObjectDecl(TObject *obj);
   int TCintWithCling__AutoLoadCallback(const char* className);
}

TClingCallbacks::TClingCallbacks(cling::Interpreter* interp)
   : InterpreterCallbacks(interp), fLastLookupCtx(0), fROOTSpecialNamespace(0),
     fFirstRun(true), fIsAutoloading(false), fIsAutoloadingRecursively(false) {
   const Decl* D = 0;
   m_Interpreter->declare("namespace __ROOT_SpecialObjects{}", &D);
   fROOTSpecialNamespace = dyn_cast<NamespaceDecl>(const_cast<Decl*>(D));
}

//pin the vtable here
TClingCallbacks::~TClingCallbacks() {}

// On a failed lookup we have to try to more things before issuing an error.
// The symbol might need to be loaded by ROOT's autoloading mechanism or
// it might be a ROOT special object.
//
// Try those first and if still failing issue the diagnostics.
//
// returns true when a declaration is found and no error should be emitted.
//
bool TClingCallbacks::LookupObject(LookupResult &R, Scope *S) {

   if (tryAutoloadInternal(R, S))
      return true; // happiness.

   // If the autoload wasn't successful try ROOT specials.
   return tryFindROOTSpecialInternal(R, S);
}

// The symbol might be defined in the ROOT class autoloading map so we have to
// try to autoload it first and do secondary lookup to try to find it.
//
// returns true when a declaration is found and no error should be emitted.
//
bool TClingCallbacks::tryAutoloadInternal(LookupResult &R, Scope *S) {
   Sema &SemaR = m_Interpreter->getSema();
   ASTContext& C = SemaR.getASTContext();
   Preprocessor &PP = SemaR.getPreprocessor();
   DeclarationName Name = R.getLookupName();

   // Try to autoload first if autoloading is enabled
   if (IsAutoloadingEnabled()) {
     // Avoid tail chasing.
     if (fIsAutoloadingRecursively)
       return false;
     fIsAutoloadingRecursively = true;

     // Save state of the PP
     Preprocessor::CleanupAndRestoreCacheRAII cleanupRAII(PP);
     Parser& P = const_cast<Parser&>(m_Interpreter->getParser());
     Parser::ParserCurTokRestoreRAII savedCurToken(P);

     bool oldSuppressDiags = SemaR.getDiagnostics().getSuppressAllDiagnostics();
     SemaR.getDiagnostics().setSuppressAllDiagnostics();

     // We can't PushDeclContext, because we go up and the routine that pops
     // the DeclContext assumes that we drill down always.
     // We have to be on the global context. At that point we are in a
     // wrapper function so the parent context must be the global.
     Sema::ContextAndScopeRAII pushedSAndDC(SemaR, C.getTranslationUnitDecl(),
                                            SemaR.TUScope);

     bool lookupSuccess = false;
     if (TCintWithCling__AutoLoadCallback(Name.getAsString().c_str())) {
       pushedSAndDC.pop();
       cleanupRAII.pop();
       lookupSuccess = SemaR.LookupName(R, S);
     }

     SemaR.getDiagnostics().setSuppressAllDiagnostics(oldSuppressDiags);

     fIsAutoloadingRecursively = false;

     if (lookupSuccess)
       return true;
   }

   return false;
}

// If cling cannot find a name it should ask ROOT before it issues an error.
// If ROOT knows the name then it has to create a new variable with that name
// and type in dedicated for that namespace (eg. __ROOT_SpecialObjects).
// For example if the interpreter is looking for h in h-Draw(), this routine
// will create
// namespace __ROOT_SpecialObjects {
//   THist* h = (THist*) the_address;
// }
//
// Later if h is called again it again won't be found by the standart lookup
// because it is in our hidden namespace (nobody should do using namespace
// __ROOT_SpecialObjects). It caches the variable declarations and their
// last address. If the newly found decl with the same name (h) has different
// address than the cached one it goes directly at the address and updates it.
//
// returns true when declaration is found and no error should be emitted.
//
bool TClingCallbacks::tryFindROOTSpecialInternal(LookupResult &R, Scope *S) {

   Sema &SemaR = m_Interpreter->getSema();
   ASTContext& C = SemaR.getASTContext();
   Preprocessor &PP = SemaR.getPreprocessor();
   DeclContext *CurDC = SemaR.CurContext;
   DeclarationName Name = R.getLookupName();

   // Make sure that the failed lookup comes from the prompt.
   if(!CurDC || !CurDC->isFunctionOrMethod())
      return false;
   if (NamedDecl* ND = dyn_cast<NamedDecl>(CurDC))
      if (!m_Interpreter->isUniqueWrapper(ND->getNameAsString()))
         return false;

   TObject *obj = TCintWithCling__GetObjectAddress(Name.getAsString().c_str(),
                                                   fLastLookupCtx);
   if (obj) {
     VarDecl *VD = cast_or_null<VarDecl>(utils::Lookup::Named(&SemaR,
                                                              Name,
                                                        fROOTSpecialNamespace));
      if (VD) {
         //TODO: Check for same types.

         TObject **address = (TObject**)m_Interpreter->getAddressOfGlobal(VD);
         // Since code was generated already we cannot rely on the initializer
         // of the decl in the AST, however we will update that init so that it
         // will be easier while debugging.
         CStyleCastExpr *CStyleCast = cast<CStyleCastExpr>(VD->getInit());
         Expr* newInit = utils::Synthesize::IntegerLiteralExpr(C, (uint64_t)obj);
         CStyleCast->setSubExpr(newInit);

         // The actual update happens here, directly in memory.
         *address = obj;
      }
      else {
         // Save state of the PP
         Preprocessor::CleanupAndRestoreCacheRAII cleanupRAII(PP);

         const Decl *TD = TCintWithCling__GetObjectDecl(obj);
         // We will declare the variable as pointer.
         QualType QT = C.getPointerType(C.getTypeDeclType(cast<TypeDecl>(TD)));

         VD = VarDecl::Create(C, fROOTSpecialNamespace, SourceLocation(),
                              SourceLocation(), Name.getAsIdentifierInfo(), QT,
                              /*TypeSourceInfo*/0, SC_None, SC_None
                              );
         // Build an initializer
         Expr* Init
           = utils::Synthesize::CStyleCastPtrExpr(&SemaR, QT, (uint64_t)obj);
         // Register the decl in our hidden special namespace
         VD->setInit(Init);
         fROOTSpecialNamespace->addDecl(VD);

         cling::CompilationOptions CO;
         CO.DeclarationExtraction = 0;
         CO.ValuePrinting = CompilationOptions::VPDisabled;
         CO.ResultEvaluation = 0;
         CO.DynamicScoping = 0;
         CO.Debug = 0;
         CO.CodeGeneration = 1;

         cling::Transaction T(CO, /*llvm::Module=*/0);
         T.appendUnique(VD);
         T.setCompleted();

         Interpreter::CompilationResult Result = m_Interpreter->codegen(&T);
         assert(Result == Interpreter::kSuccess
                && "Compilation should never fail!");
      }
      assert(VD && "Cannot be null!");
      R.addDecl(VD);
      return true;
   }

   return false;
}
// The callback is used to update the list of globals in ROOT.
//
void TClingCallbacks::TransactionCommitted(const Transaction &T) {
   if (!T.size())
      return;
   if (fFirstRun) {
      // Before setting up the callbacks register what cling have seen during init.
      const cling::Transaction* T = m_Interpreter->getFirstTransaction();
      while (T) {
         if (T->getState() == cling::Transaction::kCommitted)
            TCintWithCling__UpdateListsOnCommitted(*T);
         T = T->getNext();
      }

      fFirstRun = false;
   }

   TCintWithCling__UpdateListsOnCommitted(T);
}

// The callback is used to update the list of globals in ROOT.
//
void TClingCallbacks::TransactionUnloaded(const Transaction &T) {
   if (!T.size())
      return;

   TCintWithCling__UpdateListsOnUnloaded(T);
}
<commit_msg>After we cache the cur token, replace it with a "neutral"one. Fix warning.<commit_after>// @(#)root/core/meta:$Id$
// Author: Vassil Vassilev   7/10/2012

/*************************************************************************
 * Copyright (C) 1995-2012, Rene Brun and Fons Rademakers.               *
 * All rights reserved.                                                  *
 *                                                                       *
 * For the licensing terms see $ROOTSYS/LICENSE.                         *
 * For the list of contributors see $ROOTSYS/README/CREDITS.             *
 *************************************************************************/

#include "TClingCallbacks.h"

#include "cling/Interpreter/Interpreter.h"
#include "cling/Interpreter/InterpreterCallbacks.h"
#include "cling/Interpreter/Transaction.h"
#include "cling/Utils/AST.h"

#include "clang/AST/ASTContext.h"
#include "clang/AST/DeclBase.h"
#include "clang/Lex/Preprocessor.h"
#include "clang/Parse/Parser.h"
#include "clang/Sema/Lookup.h"
#include "clang/Sema/Scope.h"

using namespace clang;
using namespace cling;

class TObject;

// Functions used to forward calls from code compiled with no-rtti to code
// compiled with rtti.
extern "C" {
   void TCintWithCling__UpdateListsOnCommitted(const cling::Transaction&);
   void TCintWithCling__UpdateListsOnUnloaded(const cling::Transaction&);
   TObject* TCintWithCling__GetObjectAddress(const char *Name, void *&LookupCtx);
   Decl* TCintWithCling__GetObjectDecl(TObject *obj);
   int TCintWithCling__AutoLoadCallback(const char* className);
}

TClingCallbacks::TClingCallbacks(cling::Interpreter* interp)
   : InterpreterCallbacks(interp), fLastLookupCtx(0), fROOTSpecialNamespace(0),
     fFirstRun(true), fIsAutoloading(false), fIsAutoloadingRecursively(false) {
   const Decl* D = 0;
   m_Interpreter->declare("namespace __ROOT_SpecialObjects{}", &D);
   fROOTSpecialNamespace = dyn_cast<NamespaceDecl>(const_cast<Decl*>(D));
}

//pin the vtable here
TClingCallbacks::~TClingCallbacks() {}

// On a failed lookup we have to try to more things before issuing an error.
// The symbol might need to be loaded by ROOT's autoloading mechanism or
// it might be a ROOT special object.
//
// Try those first and if still failing issue the diagnostics.
//
// returns true when a declaration is found and no error should be emitted.
//
bool TClingCallbacks::LookupObject(LookupResult &R, Scope *S) {

   if (tryAutoloadInternal(R, S))
      return true; // happiness.

   // If the autoload wasn't successful try ROOT specials.
   return tryFindROOTSpecialInternal(R, S);
}

// The symbol might be defined in the ROOT class autoloading map so we have to
// try to autoload it first and do secondary lookup to try to find it.
//
// returns true when a declaration is found and no error should be emitted.
//
bool TClingCallbacks::tryAutoloadInternal(LookupResult &R, Scope *S) {
   Sema &SemaR = m_Interpreter->getSema();
   ASTContext& C = SemaR.getASTContext();
   Preprocessor &PP = SemaR.getPreprocessor();
   DeclarationName Name = R.getLookupName();

   // Try to autoload first if autoloading is enabled
   if (IsAutoloadingEnabled()) {
     // Avoid tail chasing.
     if (fIsAutoloadingRecursively)
       return false;
     fIsAutoloadingRecursively = true;

     // Save state of the PP
     Preprocessor::CleanupAndRestoreCacheRAII cleanupRAII(PP);
     Parser& P = const_cast<Parser&>(m_Interpreter->getParser());
     Parser::ParserCurTokRestoreRAII savedCurToken(P);
     // After we have saved the token reset the current one to something which
     // is safe (semi colon usually means empty decl)
     Token& Tok = const_cast<Token&>(P.getCurToken());
     Tok.setKind(tok::semi);

     bool oldSuppressDiags = SemaR.getDiagnostics().getSuppressAllDiagnostics();
     SemaR.getDiagnostics().setSuppressAllDiagnostics();

     // We can't PushDeclContext, because we go up and the routine that pops
     // the DeclContext assumes that we drill down always.
     // We have to be on the global context. At that point we are in a
     // wrapper function so the parent context must be the global.
     Sema::ContextAndScopeRAII pushedSAndDC(SemaR, C.getTranslationUnitDecl(),
                                            SemaR.TUScope);

     bool lookupSuccess = false;
     if (TCintWithCling__AutoLoadCallback(Name.getAsString().c_str())) {
       pushedSAndDC.pop();
       cleanupRAII.pop();
       lookupSuccess = SemaR.LookupName(R, S);
     }

     SemaR.getDiagnostics().setSuppressAllDiagnostics(oldSuppressDiags);

     fIsAutoloadingRecursively = false;

     if (lookupSuccess)
       return true;
   }

   return false;
}

// If cling cannot find a name it should ask ROOT before it issues an error.
// If ROOT knows the name then it has to create a new variable with that name
// and type in dedicated for that namespace (eg. __ROOT_SpecialObjects).
// For example if the interpreter is looking for h in h-Draw(), this routine
// will create
// namespace __ROOT_SpecialObjects {
//   THist* h = (THist*) the_address;
// }
//
// Later if h is called again it again won't be found by the standart lookup
// because it is in our hidden namespace (nobody should do using namespace
// __ROOT_SpecialObjects). It caches the variable declarations and their
// last address. If the newly found decl with the same name (h) has different
// address than the cached one it goes directly at the address and updates it.
//
// returns true when declaration is found and no error should be emitted.
//
bool TClingCallbacks::tryFindROOTSpecialInternal(LookupResult &R, Scope *S) {

   Sema &SemaR = m_Interpreter->getSema();
   ASTContext& C = SemaR.getASTContext();
   Preprocessor &PP = SemaR.getPreprocessor();
   DeclContext *CurDC = SemaR.CurContext;
   DeclarationName Name = R.getLookupName();

   // Make sure that the failed lookup comes from the prompt.
   if(!CurDC || !CurDC->isFunctionOrMethod())
      return false;
   if (NamedDecl* ND = dyn_cast<NamedDecl>(CurDC))
      if (!m_Interpreter->isUniqueWrapper(ND->getNameAsString()))
         return false;

   TObject *obj = TCintWithCling__GetObjectAddress(Name.getAsString().c_str(),
                                                   fLastLookupCtx);
   if (obj) {
     VarDecl *VD = cast_or_null<VarDecl>(utils::Lookup::Named(&SemaR,
                                                              Name,
                                                        fROOTSpecialNamespace));
      if (VD) {
         //TODO: Check for same types.

         TObject **address = (TObject**)m_Interpreter->getAddressOfGlobal(VD);
         // Since code was generated already we cannot rely on the initializer
         // of the decl in the AST, however we will update that init so that it
         // will be easier while debugging.
         CStyleCastExpr *CStyleCast = cast<CStyleCastExpr>(VD->getInit());
         Expr* newInit = utils::Synthesize::IntegerLiteralExpr(C, (uint64_t)obj);
         CStyleCast->setSubExpr(newInit);

         // The actual update happens here, directly in memory.
         *address = obj;
      }
      else {
         // Save state of the PP
         Preprocessor::CleanupAndRestoreCacheRAII cleanupRAII(PP);

         const Decl *TD = TCintWithCling__GetObjectDecl(obj);
         // We will declare the variable as pointer.
         QualType QT = C.getPointerType(C.getTypeDeclType(cast<TypeDecl>(TD)));

         VD = VarDecl::Create(C, fROOTSpecialNamespace, SourceLocation(),
                              SourceLocation(), Name.getAsIdentifierInfo(), QT,
                              /*TypeSourceInfo*/0, SC_None, SC_None
                              );
         // Build an initializer
         Expr* Init
           = utils::Synthesize::CStyleCastPtrExpr(&SemaR, QT, (uint64_t)obj);
         // Register the decl in our hidden special namespace
         VD->setInit(Init);
         fROOTSpecialNamespace->addDecl(VD);

         cling::CompilationOptions CO;
         CO.DeclarationExtraction = 0;
         CO.ValuePrinting = CompilationOptions::VPDisabled;
         CO.ResultEvaluation = 0;
         CO.DynamicScoping = 0;
         CO.Debug = 0;
         CO.CodeGeneration = 1;

         cling::Transaction T(CO, /*llvm::Module=*/0);
         T.appendUnique(VD);
         T.setCompleted();

         m_Interpreter->codegen(&T);
         assert(T.getState() == Transaction::kCommitted
                && "Compilation should never fail!");
      }
      assert(VD && "Cannot be null!");
      R.addDecl(VD);
      return true;
   }

   return false;
}
// The callback is used to update the list of globals in ROOT.
//
void TClingCallbacks::TransactionCommitted(const Transaction &T) {
   if (!T.size())
      return;
   if (fFirstRun) {
      // Before setting up the callbacks register what cling have seen during init.
      const cling::Transaction* T = m_Interpreter->getFirstTransaction();
      while (T) {
         if (T->getState() == cling::Transaction::kCommitted)
            TCintWithCling__UpdateListsOnCommitted(*T);
         T = T->getNext();
      }

      fFirstRun = false;
   }

   TCintWithCling__UpdateListsOnCommitted(T);
}

// The callback is used to update the list of globals in ROOT.
//
void TClingCallbacks::TransactionUnloaded(const Transaction &T) {
   if (!T.size())
      return;

   TCintWithCling__UpdateListsOnUnloaded(T);
}
<|endoftext|>


<commit_before>/*
 * Copyright (c) 2011, Willow Garage, Inc.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 *     * Redistributions of source code must retain the above copyright
 *       notice, this list of conditions and the following disclaimer.
 *     * Redistributions in binary form must reproduce the above copyright
 *       notice, this list of conditions and the following disclaimer in the
 *       documentation and/or other materials provided with the distribution.
 *     * Neither the name of the Willow Garage, Inc. nor the names of its
 *       contributors may be used to endorse or promote products derived from
 *       this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 */
#pragma once

#include <boost/shared_ptr.hpp>
#include <boost/noncopyable.hpp>
#include <boost/function.hpp>
#include <boost/bind.hpp>
#include <boost/optional.hpp>
#include <boost/typeof/std/utility.hpp>

#include <ecto/tendril.hpp>
#include <ecto/tendrils.hpp>
#include <ecto/strand.hpp>
#include <ecto/util.hpp>
#include <ecto/profile.hpp>
#include <ecto/is_threadsafe.hpp>

#include <map>

namespace ecto
{

  /**
   * \brief Return values for modules' process functions. These
   * are appropriate for non exceptional behavior.
   */
  enum ReturnCode
  {
    OK = 0, //!< Everything A OK.
    QUIT = 1,
  //!< Explicit quit now.
  };

  /**
   * \brief ecto::cell is the non virtual interface to the basic building
   * block of ecto graphs.  This interface should never be the parent of
   * client cell, but may be used for polymorphic access to client cells.
   *
   * Clients should expose their code to this interface through
   * ecto::wrap, or ecto::create_cell<T>().
   *
   * For a client's cell to satisfy the ecto::cell idium, it must
   * look similar to the following definition.
   * @code
   struct MyEctoCell
   {
     //called first thing, the user should declare their parameters in this
     //free standing function.
     static void declare_params(tendrils& params);
     //declare inputs and outputs here. The parameters may be used to
     //determine the io
     static void declare_io(const tendrils& params, tendrils& in, tendrils& out);
     //called right after allocation of the cell, exactly once.
     void configure(tendrils& params, tendrils& inputs, tendrils& outputs);
     //called at every execution of the graph
     int process(const tendrils& in, tendrils& out);
     //called right before the destructor of the cell, a good place to do
     //critical cleanup work.
     void destroy();
   };
   * @endcode
   *
   * It is important to note that all functions have are optional and they all have
   * default implementations.
   */
  struct ECTO_EXPORT cell: boost::noncopyable
  {
    typedef boost::shared_ptr<cell> ptr; //!< A convenience pointer typedef

    cell();
    virtual ~cell();

    /**
     * \brief Dispatches parameter declaration code. After this code, the parameters
     * for the cell will be set to their defaults.
     */
    void declare_params();
    /**
     * \brief Dispatches input/output declaration code.  It is assumed that the parameters
     * have been declared before this is called, so that inputs and outputs may be dependent
     * on those parameters.
     */
    void declare_io();

    /**
     * \brief Given initialized parameters,inputs, and outputs, this will dispatch the client
     * configuration code.  This will allocated an instace of the clients cell, so this
     * should not be called during introspection.
     */
    void configure();

    /**
     * \brief Dispatches the process function for the client cell.  This should only
     * be called from one thread at a time.
     *
     * Also, this function may throw exceptions...
     *
     * @return A return code, ecto::OK , or 0 means all is ok. Anything non zero should be considered an
     * exit signal.
     */
    ReturnCode process();

    /**
     * \brief This should be called at the end of life for the cell, and signals imminent destruction.
     *
     * Will dispatch the client's destroy code. After this call, do not call any other functions.
     */
    void destroy();

    /**
     * \brief Return the type of the child class.
     * @return A human readable non mangled name for the client class.
     */
    std::string type() const;

    /**
     * \brief Grab the name of the instance.
     * @return The name of the instance, or the address if none was given when object was constructed
     */
    std::string name() const;

    /**
     * \brief Set the name of the instance.
     */
    void name(const std::string&);

    /**
     * \brief Set the short_doc_ of the instance.
     */
    std::string short_doc() const;

    /**
     * \brief Set the short_doc_ of the instance.
     */
    void short_doc(const std::string&);

    /**
     * \brief Generate an Restructured Text doc string for the cell. Includes documentation for all parameters,
     * inputs, outputs.
     * @param doc The highest level documentation for the cell.
     * @return A nicely formatted doc string.
     */
    std::string gen_doc(const std::string& doc = "A module...") const;

    void verify_params() const;
    void verify_inputs() const;

    ptr clone() const;

    tendrils parameters; //!< Parameters
    tendrils inputs; //!< Inputs, inboxes, always have a valid value ( may be NULL )
    tendrils outputs; //!< Outputs, outboxes, always have a valid value ( may be NULL )
    boost::optional<strand> strand_;
    profile::stats_type stats;

  protected:

    virtual void init() = 0;
    virtual void dispatch_declare_params(tendrils& t) = 0;
    virtual void dispatch_declare_io(const tendrils& params, tendrils& inputs,
                                     tendrils& outputs) = 0;
    virtual void dispatch_configure(tendrils& params, tendrils& inputs,
                                    tendrils& outputs) = 0;
    virtual ReturnCode
    dispatch_process(tendrils& inputs, tendrils& outputs) = 0;
    virtual void dispatch_destroy() = 0;
    virtual std::string dispatch_name() const = 0;
    virtual ptr dispatch_make() const
    {
      return ptr();
    }

    virtual std::string dispatch_short_doc() const
    {
      return "";
    }

    virtual void dispatch_short_doc(const std::string&)
    {
    }
  private:
    std::string instance_name_;
  };

  /**
   * \brief Helper class for determining if client modules have function
   * implementations or not.
   * @internal
   */
  template<class T>
  struct has_f
  {
    typedef char yes;
    typedef char (&no)[2];

    // SFINAE eliminates this when the type of arg is invalid
    template<class U>
    static yes test_declare_params(BOOST_TYPEOF_TPL(&U::declare_params));
    // overload resolution prefers anything at all over "..."
    template<class U>
    static no test_declare_params(...);

    template<class U>
    static yes test_declare_io(BOOST_TYPEOF_TPL(&U::declare_io));
    template<class U>
    static no test_declare_io(...);

    template<class U>
    static yes test_configure(BOOST_TYPEOF_TPL(&U::configure));
    template<class U>
    static no test_configure(...);

    template<class U>
    static yes test_process(BOOST_TYPEOF_TPL(&U::process));
    template<class U>
    static no test_process(...);

    template<class U>
    static yes test_destroy(BOOST_TYPEOF_TPL(&U::destroy));
    template<class U>
    static no test_destroy(...);

    enum
    {
      declare_params = sizeof(test_declare_params<T> (0)) == sizeof(yes)
    };
    enum
    {
      declare_io = sizeof(test_declare_io<T> (0)) == sizeof(yes)
    };
    enum
    {
      configure = sizeof(test_configure<T> (0)) == sizeof(yes)
    };
    enum
    {
      process = sizeof(test_process<T> (0)) == sizeof(yes)
    };
    enum
    {
      destroy = sizeof(test_destroy<T> (0)) == sizeof(yes)
    };

  };

  /**
   * \brief cell_<T> is for registering an arbitrary class
   * with the the cell NVI. This adds a barrier between client code and the cell.
   */
  template<class Impl>
  struct cell_: cell
  {
    typedef boost::shared_ptr<cell_<Impl> > ptr;

    typedef typename detail::python_mutex<Impl>::type gil_mtx_t;

    ~cell_()
    {
      dispatch_destroy();
    }
  protected:
    template<int I>
    struct int_
    {
    };
    typedef int_<0> not_implemented;
    typedef int_<1> implemented;

    static void declare_params(not_implemented, tendrils& params)
    {
    }

    static void declare_params(implemented, tendrils& params)
    {
      Impl::declare_params(params);
    }

    void dispatch_declare_params(tendrils& params)
    {
      //this is a none static function. for virtuality.
      declare_params(int_<has_f<Impl>::declare_params> (), params);
    }

    static void declare_io(not_implemented, const tendrils& params,
                           tendrils& inputs, tendrils& outputs)
    {
    }
    static void declare_io(implemented, const tendrils& params,
                           tendrils& inputs, tendrils& outputs)
    {
      Impl::declare_io(params, inputs, outputs);
    }

    void dispatch_declare_io(const tendrils& params, tendrils& inputs,
                             tendrils& outputs)
    {
      declare_io(int_<has_f<Impl>::declare_io> (), params, inputs, outputs);
    }

    void configure(not_implemented, tendrils&, tendrils& , tendrils&)
    {
    }

    void configure(implemented, tendrils& params, tendrils& inputs,
                   tendrils& outputs)
    {
      boost::this_thread::interruption_point();
      gil_mtx_t gillock();
      impl->configure(params,inputs,outputs);
    }

    void dispatch_configure(tendrils& params, tendrils& inputs,
                            tendrils& outputs)
    {
      //the cell may not be allocated here, so check pointer.
      if (!impl)
      {
        try
        {
          impl.reset(new Impl);
        }
        catch (std::exception& e)
        {
          except::EctoException ee("Original Exception: " +name_of(typeid(e)));
          ee << "  What   : " + std::string(e.what());
          ee << "  Module : " + name() + "\n  in constructor of: " + name_of<Impl>();
          boost::throw_exception(ee); \
        }
        catch (...)
        {
          except::EctoException ee("Threw unknown exception type!");
          ee << "  Module : " + name() + "\n  in constructor of: " + name_of<Impl>();
          boost::throw_exception(ee);
        }
        //configure is only called once.
        configure(int_<has_f<Impl>::configure> (), params,inputs,outputs);
      }
    }

    ReturnCode process(not_implemented, const tendrils& ,
                       const tendrils& )
    {
      return OK;
    }

    ReturnCode process(implemented, tendrils& inputs, tendrils& outputs)
    {
      gil_mtx_t gillock;
      ReturnCode code;
      profile::stats_collector coll(stats);
      code = ReturnCode(impl->process(inputs, outputs));
      return code;
    }

    ReturnCode dispatch_process(tendrils& inputs, tendrils& outputs)
    {
      dispatch_configure(parameters,this->inputs,outputs);
      boost::this_thread::interruption_point();
      return process(int_<has_f<Impl>::process> (), inputs, outputs);
    }

    void destroy(not_implemented)
    {
    }

    void destroy(implemented)
    {
      //destroy only called once, then destructor.
      if(impl)
        impl->destroy();
    }

    void dispatch_destroy()
    {
      destroy(int_<has_f<Impl>::destroy> ());
      impl.reset();
    }

    std::string dispatch_name() const
    {
      return CELL_TYPE_NAME;
    }
    std::string dispatch_short_doc() const
    {
      return SHORT_DOC;
    }

    void dispatch_short_doc(const std::string&)
    {
    }

    cell::ptr dispatch_make() const
    {
      cell::ptr m(new cell_<Impl> ());
      m->declare_params();
      //copy all of the parameters by value.
      tendrils::iterator it = m->parameters.begin();
      tendrils::const_iterator end = m->parameters.end(), oit =
          parameters.begin();
      while (it != end)
        {
          it->second << *oit->second;
          ++oit;
          ++it;
        }
      m->declare_io();
      return m;
    }
    void init()
    {
      if(!impl)
      {
        cell::configure();
      }
    }

    static const std::string CELL_TYPE_NAME;
  public:
    boost::shared_ptr<Impl> impl;
    static std::string SHORT_DOC;
  };

  template<typename Impl>
  std::string cell_<Impl>::SHORT_DOC;

  template<typename Impl>
  const std::string cell_<Impl>::CELL_TYPE_NAME = ecto::name_of<Impl>();

  /**
   * Creates a cell from type T that has not been configured, so therefore,
   * not allocated.  This only calls the static functions associated with parameter and
   * input/output declaration.
   *
   * @return A cell::ptr that is initialized as far as default params,inputs,outputs go.
   */
  template<typename Impl>
  typename cell_<Impl>::ptr inspect_cell()
  {
    typename cell_<Impl>::ptr p(new cell_<Impl> ());
    cell::ptr base(p);
    base->declare_params();
    base->declare_io();
    return p;
  }

  /**
   * Create a cell from an type that has all of the proper interface functions defined.
   * This will call configure in the cell.
   * @return A cell ptr.
   */
  template<typename Impl>
  typename cell_<Impl>::ptr create_cell()
  {
    typename cell_<Impl>::ptr p = inspect_cell<Impl>();
    return p;
  }

}//namespace ecto
<commit_msg>rm gil lock, verify that python objects aren't passed as in/outputs<commit_after>/*
 * Copyright (c) 2011, Willow Garage, Inc.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 *     * Redistributions of source code must retain the above copyright
 *       notice, this list of conditions and the following disclaimer.
 *     * Redistributions in binary form must reproduce the above copyright
 *       notice, this list of conditions and the following disclaimer in the
 *       documentation and/or other materials provided with the distribution.
 *     * Neither the name of the Willow Garage, Inc. nor the names of its
 *       contributors may be used to endorse or promote products derived from
 *       this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 */
#pragma once

#include <boost/shared_ptr.hpp>
#include <boost/noncopyable.hpp>
#include <boost/function.hpp>
#include <boost/bind.hpp>
#include <boost/optional.hpp>
#include <boost/typeof/std/utility.hpp>

#include <ecto/tendril.hpp>
#include <ecto/tendrils.hpp>
#include <ecto/strand.hpp>
#include <ecto/util.hpp>
#include <ecto/profile.hpp>
#include <ecto/is_threadsafe.hpp>

#include <map>

namespace ecto
{

  /**
   * \brief Return values for modules' process functions. These
   * are appropriate for non exceptional behavior.
   */
  enum ReturnCode
  {
    OK = 0, //!< Everything A OK.
    QUIT = 1,
  //!< Explicit quit now.
  };

  /**
   * \brief ecto::cell is the non virtual interface to the basic building
   * block of ecto graphs.  This interface should never be the parent of
   * client cell, but may be used for polymorphic access to client cells.
   *
   * Clients should expose their code to this interface through
   * ecto::wrap, or ecto::create_cell<T>().
   *
   * For a client's cell to satisfy the ecto::cell idium, it must
   * look similar to the following definition.
   * @code
   struct MyEctoCell
   {
     //called first thing, the user should declare their parameters in this
     //free standing function.
     static void declare_params(tendrils& params);
     //declare inputs and outputs here. The parameters may be used to
     //determine the io
     static void declare_io(const tendrils& params, tendrils& in, tendrils& out);
     //called right after allocation of the cell, exactly once.
     void configure(tendrils& params, tendrils& inputs, tendrils& outputs);
     //called at every execution of the graph
     int process(const tendrils& in, tendrils& out);
     //called right before the destructor of the cell, a good place to do
     //critical cleanup work.
     void destroy();
   };
   * @endcode
   *
   * It is important to note that all functions have are optional and they all have
   * default implementations.
   */
  struct ECTO_EXPORT cell: boost::noncopyable
  {
    typedef boost::shared_ptr<cell> ptr; //!< A convenience pointer typedef

    cell();
    virtual ~cell();

    /**
     * \brief Dispatches parameter declaration code. After this code, the parameters
     * for the cell will be set to their defaults.
     */
    void declare_params();
    /**
     * \brief Dispatches input/output declaration code.  It is assumed that the parameters
     * have been declared before this is called, so that inputs and outputs may be dependent
     * on those parameters.
     */
    void declare_io();

    /**
     * \brief Given initialized parameters,inputs, and outputs, this will dispatch the client
     * configuration code.  This will allocated an instace of the clients cell, so this
     * should not be called during introspection.
     */
    void configure();

    /**
     * \brief Dispatches the process function for the client cell.  This should only
     * be called from one thread at a time.
     *
     * Also, this function may throw exceptions...
     *
     * @return A return code, ecto::OK , or 0 means all is ok. Anything non zero should be considered an
     * exit signal.
     */
    ReturnCode process();

    /**
     * \brief This should be called at the end of life for the cell, and signals imminent destruction.
     *
     * Will dispatch the client's destroy code. After this call, do not call any other functions.
     */
    void destroy();

    /**
     * \brief Return the type of the child class.
     * @return A human readable non mangled name for the client class.
     */
    std::string type() const;

    /**
     * \brief Grab the name of the instance.
     * @return The name of the instance, or the address if none was given when object was constructed
     */
    std::string name() const;

    /**
     * \brief Set the name of the instance.
     */
    void name(const std::string&);

    /**
     * \brief Set the short_doc_ of the instance.
     */
    std::string short_doc() const;

    /**
     * \brief Set the short_doc_ of the instance.
     */
    void short_doc(const std::string&);

    /**
     * \brief Generate an Restructured Text doc string for the cell. Includes documentation for all parameters,
     * inputs, outputs.
     * @param doc The highest level documentation for the cell.
     * @return A nicely formatted doc string.
     */
    std::string gen_doc(const std::string& doc = "A module...") const;

    void verify_params() const;
    void verify_inputs() const;

    ptr clone() const;

    tendrils parameters; //!< Parameters
    tendrils inputs; //!< Inputs, inboxes, always have a valid value ( may be NULL )
    tendrils outputs; //!< Outputs, outboxes, always have a valid value ( may be NULL )
    boost::optional<strand> strand_;
    profile::stats_type stats;

  protected:

    virtual void init() = 0;
    virtual void dispatch_declare_params(tendrils& t) = 0;
    virtual void dispatch_declare_io(const tendrils& params, tendrils& inputs,
                                     tendrils& outputs) = 0;
    virtual void dispatch_configure(tendrils& params, tendrils& inputs,
                                    tendrils& outputs) = 0;
    virtual ReturnCode
    dispatch_process(tendrils& inputs, tendrils& outputs) = 0;
    virtual void dispatch_destroy() = 0;
    virtual std::string dispatch_name() const = 0;
    virtual ptr dispatch_make() const
    {
      return ptr();
    }

    virtual std::string dispatch_short_doc() const
    {
      return "";
    }

    virtual void dispatch_short_doc(const std::string&)
    {
    }
  private:
    std::string instance_name_;
  };

  /**
   * \brief Helper class for determining if client modules have function
   * implementations or not.
   * @internal
   */
  template<class T>
  struct has_f
  {
    typedef char yes;
    typedef char (&no)[2];

    // SFINAE eliminates this when the type of arg is invalid
    template<class U>
    static yes test_declare_params(BOOST_TYPEOF_TPL(&U::declare_params));
    // overload resolution prefers anything at all over "..."
    template<class U>
    static no test_declare_params(...);

    template<class U>
    static yes test_declare_io(BOOST_TYPEOF_TPL(&U::declare_io));
    template<class U>
    static no test_declare_io(...);

    template<class U>
    static yes test_configure(BOOST_TYPEOF_TPL(&U::configure));
    template<class U>
    static no test_configure(...);

    template<class U>
    static yes test_process(BOOST_TYPEOF_TPL(&U::process));
    template<class U>
    static no test_process(...);

    template<class U>
    static yes test_destroy(BOOST_TYPEOF_TPL(&U::destroy));
    template<class U>
    static no test_destroy(...);

    enum
    {
      declare_params = sizeof(test_declare_params<T> (0)) == sizeof(yes)
    };
    enum
    {
      declare_io = sizeof(test_declare_io<T> (0)) == sizeof(yes)
    };
    enum
    {
      configure = sizeof(test_configure<T> (0)) == sizeof(yes)
    };
    enum
    {
      process = sizeof(test_process<T> (0)) == sizeof(yes)
    };
    enum
    {
      destroy = sizeof(test_destroy<T> (0)) == sizeof(yes)
    };

  };

  /**
   * \brief cell_<T> is for registering an arbitrary class
   * with the the cell NVI. This adds a barrier between client code and the cell.
   */
  template<class Impl>
  struct cell_: cell
  {
    typedef boost::shared_ptr<cell_<Impl> > ptr;

    typedef typename detail::python_mutex<Impl>::type gil_mtx_t;

    ~cell_()
    {
      dispatch_destroy();
    }
  protected:
    template<int I>
    struct int_
    {
    };
    typedef int_<0> not_implemented;
    typedef int_<1> implemented;

    static void declare_params(not_implemented, tendrils& params)
    {
    }

    static void declare_params(implemented, tendrils& params)
    {
      Impl::declare_params(params);
    }

    void dispatch_declare_params(tendrils& params)
    {
      //this is a none static function. for virtuality.
      declare_params(int_<has_f<Impl>::declare_params> (), params);
    }

    static void declare_io(not_implemented, const tendrils& params,
                           tendrils& inputs, tendrils& outputs)
    {
    }
    static void declare_io(implemented, const tendrils& params,
                           tendrils& inputs, tendrils& outputs)
    {
      Impl::declare_io(params, inputs, outputs);
    }

    void dispatch_declare_io(const tendrils& params, tendrils& inputs,
                             tendrils& outputs)
    {
      declare_io(int_<has_f<Impl>::declare_io> (), params, inputs, outputs);
    }

    void configure(not_implemented, tendrils&, tendrils& , tendrils&)
    {
    }

    void configure(implemented, tendrils& params, tendrils& inputs,
                   tendrils& outputs)
    {
      boost::this_thread::interruption_point();
      impl->configure(params,inputs,outputs);
      for (tendrils::iterator iter = inputs.begin(); iter != inputs.end(); ++iter)
        if (iter->second->is_type<boost::python::object>())
          throw std::runtime_error("you can't use a python object as an input");

      for (tendrils::iterator iter = outputs.begin(); iter != outputs.end(); ++iter)
        if (iter->second->is_type<boost::python::object>())
          throw std::runtime_error("you can't use a python object as an output");

    }

    void dispatch_configure(tendrils& params, tendrils& inputs,
                            tendrils& outputs)
    {
      //the cell may not be allocated here, so check pointer.
      if (!impl)
      {
        try
        {
          impl.reset(new Impl);
        }
        catch (std::exception& e)
        {
          except::EctoException ee("Original Exception: " +name_of(typeid(e)));
          ee << "  What   : " + std::string(e.what());
          ee << "  Module : " + name() + "\n  in constructor of: " + name_of<Impl>();
          boost::throw_exception(ee); \
        }
        catch (...)
        {
          except::EctoException ee("Threw unknown exception type!");
          ee << "  Module : " + name() + "\n  in constructor of: " + name_of<Impl>();
          boost::throw_exception(ee);
        }
        //configure is only called once.
        configure(int_<has_f<Impl>::configure> (), params,inputs,outputs);
      }
    }

    ReturnCode process(not_implemented, const tendrils& ,
                       const tendrils& )
    {
      return OK;
    }

    ReturnCode process(implemented, tendrils& inputs, tendrils& outputs)
    {
      ReturnCode code;
      profile::stats_collector coll(stats);
      code = ReturnCode(impl->process(inputs, outputs));
      return code;
    }

    ReturnCode dispatch_process(tendrils& inputs, tendrils& outputs)
    {
      dispatch_configure(parameters,this->inputs,outputs);
      boost::this_thread::interruption_point();
      return process(int_<has_f<Impl>::process> (), inputs, outputs);
    }

    void destroy(not_implemented)
    {
    }

    void destroy(implemented)
    {
      //destroy only called once, then destructor.
      if(impl)
        impl->destroy();
    }

    void dispatch_destroy()
    {
      destroy(int_<has_f<Impl>::destroy> ());
      impl.reset();
    }

    std::string dispatch_name() const
    {
      return CELL_TYPE_NAME;
    }
    std::string dispatch_short_doc() const
    {
      return SHORT_DOC;
    }

    void dispatch_short_doc(const std::string&)
    {
    }

    cell::ptr dispatch_make() const
    {
      cell::ptr m(new cell_<Impl> ());
      m->declare_params();
      //copy all of the parameters by value.
      tendrils::iterator it = m->parameters.begin();
      tendrils::const_iterator end = m->parameters.end(), oit =
          parameters.begin();
      while (it != end)
        {
          it->second << *oit->second;
          ++oit;
          ++it;
        }
      m->declare_io();
      return m;
    }
    void init()
    {
      if(!impl)
      {
        cell::configure();
      }
    }

    static const std::string CELL_TYPE_NAME;
  public:
    boost::shared_ptr<Impl> impl;
    static std::string SHORT_DOC;
  };

  template<typename Impl>
  std::string cell_<Impl>::SHORT_DOC;

  template<typename Impl>
  const std::string cell_<Impl>::CELL_TYPE_NAME = ecto::name_of<Impl>();

  /**
   * Creates a cell from type T that has not been configured, so therefore,
   * not allocated.  This only calls the static functions associated with parameter and
   * input/output declaration.
   *
   * @return A cell::ptr that is initialized as far as default params,inputs,outputs go.
   */
  template<typename Impl>
  typename cell_<Impl>::ptr inspect_cell()
  {
    typename cell_<Impl>::ptr p(new cell_<Impl> ());
    cell::ptr base(p);
    base->declare_params();
    base->declare_io();
    return p;
  }

  /**
   * Create a cell from an type that has all of the proper interface functions defined.
   * This will call configure in the cell.
   * @return A cell ptr.
   */
  template<typename Impl>
  typename cell_<Impl>::ptr create_cell()
  {
    typename cell_<Impl>::ptr p = inspect_cell<Impl>();
    return p;
  }

}//namespace ecto
<|endoftext|>


<commit_before>#include <string>
#include <iostream>

#include "pneu/graphics/Color.hpp"
#include "pneu/graphics/Window.hpp"
#include "pneu/graphics/Renderer.hpp"
#include "pneu/core/MethodResult.hpp"

#define GLM_FORCE_CXX11
#define GLM_FORCE_RADIANS
#include <glm/glm.hpp>

auto main(int argc, const char** argv) -> int {
  pneu::graphics::Window window("testing", 800, 600, 80, 60);

  window.init().onError([](const std::string& error) {
                          std::cout << error << std::endl;
                          exit(1);
                        });

  // set background to a nice shade of blue
  window.getRenderer().setBackgroundColor(pneu::graphics::Color<>(0.2f, 0.3f, 0.7f));

  while (window.isRunning()) {
    window.pollEvents();
    window.update();
    window.renderFrame();
  }

  return 0;
}
<commit_msg>Added Ellipse drawing line (uncomment to segfault :-(<commit_after>#include <string>
#include <iostream>

#include "pneu/graphics/Color.hpp"
#include "pneu/graphics/Window.hpp"
#include "pneu/graphics/Renderer.hpp"

#include "pneu/graphics/shapes/Ellipse.hpp"

#include "pneu/core/MethodResult.hpp"

#define GLM_FORCE_CXX11
#define GLM_FORCE_RADIANS
#include <glm/glm.hpp>

auto main(int argc, const char** argv) -> int {
  pneu::graphics::Window window("testing", 800, 600, 80, 60);

  window.init().onError([](const std::string& error) {
                          std::cout << error << std::endl;
                          exit(1);
                        });

  // set background to a nice shade of blue
  window.getRenderer().setBackgroundColor(pneu::graphics::Color<>(0.2f, 0.3f, 0.7f));
  /*
  window.getRenderer().addRenderObject(
    std::make_shared<pneu::graphics::shapes::Ellipse>(glm::vec2(0.0f),
                                                      pneu::graphics::Color<>::red(),
                                                      5.0f));
  */
  while (window.isRunning()) {
    window.pollEvents();
    window.update();
    window.renderFrame();
  }

  return 0;
}
<|endoftext|>


<commit_before>// Copyright (c) 2012 Plenluno All rights reserved.

#include <assert.h>
#include <stdio.h>
#include <iv/lv5/third_party/v8_dtoa/conversions.h>
#include <string>

#include "libj/string.h"
#include "./glue/cvtutf.h"

namespace libj {

class StringImpl : public String {
 public:
    Size length() const {
        return str_.length();
    }

    Char charAt(Size index) const {
        if (index >= length()) {
            return NO_CHAR;
        } else {
            return str_.at(index);
        }
    }

    CPtr substring(Size from) const {
        if (from > length()) {
            return null();
        } else if (from == 0) {
            return toString();
        } else {
            CPtr p(new StringImpl(*this, from));
            return p;
        }
    }

    CPtr substring(Size from, Size to) const {
        Size len = length();
        if (from > len || to > len || from > to) {
            return null();
        } else if (from == 0 && to == len) {
            return toString();
        } else {
            CPtr p(new StringImpl(*this, from, to - from));
            return p;
        }
    }

    CPtr concat(CPtr other) const {
        if (!other || other->isEmpty()) {
            return this->toString();
        } else if (this->isEmpty()) {
            return other->toString();
        }

        StringImpl* s = new StringImpl(*this);
        Size len = other->length();
        for (Size i = 0; i < len; i++)
            s->str_.push_back(other->charAt(i));
        CPtr p(s);
        return p;
    }

    Int compareTo(Object::CPtr that) const {
        Int result = Object::compareTo(that);
        if (result != TYPE_CMP_SAME &&
            result != -TYPE_CMP_SAME) {
            return result;
        }

        String::CPtr other = LIBJ_STATIC_CPTR_CAST(String)(that);
        Size len1 = this->length();
        Size len2 = other->length();
        Size len = len1 < len2 ? len1 : len2;
        for (Size i = 0; i < len; i++) {
            Char c1 = this->charAt(i);
            Char c2 = other->charAt(i);
            if (c1 != c2)
                return c1 - c2;
        }
        return len1 - len2;
    }

    Boolean startsWith(CPtr other, Size from) const {
        Size len1 = this->length();
        Size len2 = other->length();
        if (len1 < from + len2)
            return false;
        for (Size i = 0; i < len2; i++)
            if (this->charAt(from + i) != other->charAt(i))
                return false;
        return true;
    }

    Boolean endsWith(CPtr other) const {
        Size len1 = this->length();
        Size len2 = other->length();
        if (len1 < len2)
            return false;
        Size pos = len1 - len2;
        for (Size i = 0; i < len2; i++)
            if (this->charAt(pos + i) != other->charAt(i))
                return false;
        return true;
    }

    Size indexOf(Char c, Size from) const {
        Size len = length();
        for (Size i = from; i < len; i++)
            if (charAt(i) == c)
                return i;
        return NO_POS;
    }

    Size indexOf(CPtr other, Size from) const {
        // TODO(plenluno): make it more efficient
        Size len1 = this->length();
        Size len2 = other->length();
        if (len1 < from + len2)
            return NO_POS;
        Size n = len1 - len2 + 1;
        for (Size i = from; i < n; i++)
            if (startsWith(other, i))
                return i;
        return NO_POS;
    }

    Size lastIndexOf(Char c, Size from) const {
        Size len = length();
        if (len == 0)
            return NO_POS;
        from = from < len ? from : len - 1;
        for (Size i = from; ; i--) {
            if (charAt(i) == c)
                return i;
            if (i == 0)
                break;
        }
        return NO_POS;
    }

    Size lastIndexOf(CPtr other, Size from) const {
        // TODO(plenluno): make it more efficient
        Size len1 = this->length();
        Size len2 = other->length();
        if (len1 < len2)
            return NO_POS;
        Size diff = len1 - len2;
        from = from < diff ? from : diff;
        for (Size i = from; ; i--) {
            if (startsWith(other, i))
                return i;
            if (i == 0)
                break;
        }
        return NO_POS;
    }

    Boolean isEmpty() const {
        return length() == 0;
    }

    CPtr toLowerCase() const {
        Size len = length();
        StringImpl* s = new StringImpl();
        for (Size i = 0; i < len; i++) {
            Char c = charAt(i);
            if (c >= 'A' && c <= 'Z')
                c += 'a' - 'A';
            s->str_ += c;
        }
        CPtr p(s);
        return p;
    }

    CPtr toUpperCase() const {
        Size len = length();
        StringImpl* s = new StringImpl();
        for (Size i = 0; i < len; i++) {
            Char c = charAt(i);
            if (c >= 'a' && c <= 'z')
                c -= 'a' - 'A';
            s->str_ += c;
        }
        CPtr p(s);
        return p;
    }

    CPtr toString() const {
        CPtr p(new StringImpl(*this));
        return p;
    }

    std::u16string toStdU16String() const {
        return glue::utf32ToUtf16(str_);
    }

    std::u32string toStdU32String() const {
        return str_;
    }

    std::string toStdString(Encoding enc) const {
        return glue::fromUtf32(str_, convertEncoding(enc));
    }

    static CPtr create() {
        CPtr p(new StringImpl());
        return p;
    }

    static CPtr create(Char c, Size n) {
        CPtr p(new StringImpl(c, n));
        return p;
    }

    static CPtr create(const std::u16string& s16) {
        CPtr p(new StringImpl(s16));
        return p;
    }

    static CPtr create(const std::u32string& s32) {
        CPtr p(new StringImpl(s32));
        return p;
    }

    static CPtr create(const void* data, Encoding enc, Size max) {
        CPtr p(new StringImpl(data, enc, max));
        return p;
    }

 private:
    static glue::UnicodeEncoding convertEncoding(Encoding enc) {
        switch (enc) {
        case UTF8:
            return glue::UTF8;
        case UTF16BE:
            return glue::UTF16BE;
        case UTF16LE:
            return glue::UTF16LE;
        case UTF32BE:
            return glue::UTF32BE;
        case UTF32LE:
            return glue::UTF32LE;
        default:
            assert(false);
        }
    }

 private:
    std::u32string str_;

    StringImpl() : str_() {}

    StringImpl(Char c, Size n) : str_(n, c) {}

    StringImpl(const std::u16string& s16)
        : str_(glue::utf16ToUtf32(s16)) {}

    StringImpl(const std::u32string& s32) : str_(s32) {}

    StringImpl(const void* data, Encoding enc, Size max)
        : str_(glue::toUtf32(data, convertEncoding(enc), max)) {}

    StringImpl(const StringImpl& other) : str_(other.str_) {}

    StringImpl(const StringImpl& other, Size pos, Size count = NO_POS)
        : str_(other.str_, pos, count) {}
};

String::CPtr String::create() {
    static const String::CPtr empty =
        StringImpl::create(NULL, UTF8, NO_POS);
    return empty;
}

String::CPtr String::create(Char c, Size n) {
    return StringImpl::create(c, n);
}

String::CPtr String::create(const std::u16string& s16) {
    return StringImpl::create(s16);
}

String::CPtr String::create(const std::u32string& s32) {
    return StringImpl::create(s32);
}

String::CPtr String::create(const void* data, Encoding enc, Size max) {
    return StringImpl::create(data, enc, max);
}

static String::CPtr LIBJ_STR_TRUE = String::create("true");
static String::CPtr LIBJ_STR_FALSE = String::create("false");

static String::CPtr booleanToString(const Value& val) {
    Boolean b;
    to<Boolean>(val, &b);
    return b ? LIBJ_STR_TRUE : LIBJ_STR_FALSE;
}

static String::CPtr byteToString(const Value& val) {
    Byte b;
    to<Byte>(val, &b);
    const Size kLen = (8 / 3) + 3;
    char s[kLen];
    snprintf(s, kLen, "%d", b);
    return String::create(s);
}

static String::CPtr shortToString(const Value& val) {
    Short sh;
    to<Short>(val, &sh);
    const Size kLen = (16 / 3) + 3;
    char s[kLen];
    snprintf(s, kLen, "%d", sh);
    return String::create(s);
}

static String::CPtr intToString(const Value& val) {
    Int i;
    to<Int>(val, &i);
    const Size kLen = (32 / 3) + 3;
    char s[kLen];
    snprintf(s, kLen, "%d", i);
    String::CPtr p = String::create(s);
    return p;
}

static String::CPtr longToString(const Value& val) {
    Long l;
    to<Long>(val, &l);
    const Size kLen = (64 / 3) + 3;
    char s[kLen];
    snprintf(s, kLen, "%lld", l);
    return String::create(s);
}

static String::CPtr floatToString(const Value& val) {
    Float f;
    to<Float>(val, &f);
    const Size kLen = 64;
    char s[kLen];
    return String::create(v8::internal::DoubleToCString(f, s, kLen));
}

static String::CPtr doubleToString(const Value& val) {
    Double d;
    to<Double>(val, &d);
    const Size kLen = 64;
    char s[kLen];
    return String::create(v8::internal::DoubleToCString(d, s, kLen));
}

static String::CPtr sizeToString(const Value& val) {
    Size n;
    to<Size>(val, &n);
    const Size kLen = ((sizeof(Size) << 3) / 3) + 3;
    char s[kLen];
    snprintf(s, kLen, "%zd", n);
    String::CPtr p = String::create(s);
    return p;
}

static String::CPtr typeIdToString(const Value& val) {
    TypeId t;
    to<TypeId>(val, &t);
    const Size kLen = ((sizeof(TypeId) << 3) / 3) + 3;
    char s[kLen];
    snprintf(s, kLen, "%zd", t);
    String::CPtr p = String::create(s);
    return p;
}

static String::CPtr objectToString(const Value& val) {
    Object::CPtr o = toCPtr<Object>(val);
    if (o) {
        return o->toString();
    } else {
        return String::null();
    }
}

String::CPtr String::valueOf(const Value& val) {
    if (val.isEmpty()) {
        return null();
    } else if (val.type() == Type<Boolean>::id()) {
        return booleanToString(val);
    } else if (val.type() == Type<Byte>::id()) {
        return byteToString(val);
    } else if (val.type() == Type<Short>::id()) {
        return shortToString(val);
    } else if (val.type() == Type<Int>::id()) {
        return intToString(val);
    } else if (val.type() == Type<Long>::id()) {
        return longToString(val);
    } else if (val.type() == Type<Float>::id()) {
        return floatToString(val);
    } else if (val.type() == Type<Double>::id()) {
        return doubleToString(val);
    } else if (val.type() == Type<Size>::id()) {
        return sizeToString(val);
    } else if (val.type() == Type<TypeId>::id()) {
        return typeIdToString(val);
    } else if (val.instanceof(Type<Object>::id())) {
        return objectToString(val);
    } else {
        return null();
    }
}

}  // namespace libj
<commit_msg>refactor String::valueOf<commit_after>// Copyright (c) 2012 Plenluno All rights reserved.

#include <assert.h>
#include <stdio.h>
#include <iv/lv5/third_party/v8_dtoa/conversions.h>
#include <string>

#include "libj/string.h"
#include "./glue/cvtutf.h"

namespace libj {

class StringImpl : public String {
 public:
    Size length() const {
        return str_.length();
    }

    Char charAt(Size index) const {
        if (index >= length()) {
            return NO_CHAR;
        } else {
            return str_.at(index);
        }
    }

    CPtr substring(Size from) const {
        if (from > length()) {
            return null();
        } else if (from == 0) {
            return toString();
        } else {
            CPtr p(new StringImpl(*this, from));
            return p;
        }
    }

    CPtr substring(Size from, Size to) const {
        Size len = length();
        if (from > len || to > len || from > to) {
            return null();
        } else if (from == 0 && to == len) {
            return toString();
        } else {
            CPtr p(new StringImpl(*this, from, to - from));
            return p;
        }
    }

    CPtr concat(CPtr other) const {
        if (!other || other->isEmpty()) {
            return this->toString();
        } else if (this->isEmpty()) {
            return other->toString();
        }

        StringImpl* s = new StringImpl(*this);
        Size len = other->length();
        for (Size i = 0; i < len; i++)
            s->str_.push_back(other->charAt(i));
        CPtr p(s);
        return p;
    }

    Int compareTo(Object::CPtr that) const {
        Int result = Object::compareTo(that);
        if (result != TYPE_CMP_SAME &&
            result != -TYPE_CMP_SAME) {
            return result;
        }

        String::CPtr other = LIBJ_STATIC_CPTR_CAST(String)(that);
        Size len1 = this->length();
        Size len2 = other->length();
        Size len = len1 < len2 ? len1 : len2;
        for (Size i = 0; i < len; i++) {
            Char c1 = this->charAt(i);
            Char c2 = other->charAt(i);
            if (c1 != c2)
                return c1 - c2;
        }
        return len1 - len2;
    }

    Boolean startsWith(CPtr other, Size from) const {
        Size len1 = this->length();
        Size len2 = other->length();
        if (len1 < from + len2)
            return false;
        for (Size i = 0; i < len2; i++)
            if (this->charAt(from + i) != other->charAt(i))
                return false;
        return true;
    }

    Boolean endsWith(CPtr other) const {
        Size len1 = this->length();
        Size len2 = other->length();
        if (len1 < len2)
            return false;
        Size pos = len1 - len2;
        for (Size i = 0; i < len2; i++)
            if (this->charAt(pos + i) != other->charAt(i))
                return false;
        return true;
    }

    Size indexOf(Char c, Size from) const {
        Size len = length();
        for (Size i = from; i < len; i++)
            if (charAt(i) == c)
                return i;
        return NO_POS;
    }

    Size indexOf(CPtr other, Size from) const {
        // TODO(plenluno): make it more efficient
        Size len1 = this->length();
        Size len2 = other->length();
        if (len1 < from + len2)
            return NO_POS;
        Size n = len1 - len2 + 1;
        for (Size i = from; i < n; i++)
            if (startsWith(other, i))
                return i;
        return NO_POS;
    }

    Size lastIndexOf(Char c, Size from) const {
        Size len = length();
        if (len == 0)
            return NO_POS;
        from = from < len ? from : len - 1;
        for (Size i = from; ; i--) {
            if (charAt(i) == c)
                return i;
            if (i == 0)
                break;
        }
        return NO_POS;
    }

    Size lastIndexOf(CPtr other, Size from) const {
        // TODO(plenluno): make it more efficient
        Size len1 = this->length();
        Size len2 = other->length();
        if (len1 < len2)
            return NO_POS;
        Size diff = len1 - len2;
        from = from < diff ? from : diff;
        for (Size i = from; ; i--) {
            if (startsWith(other, i))
                return i;
            if (i == 0)
                break;
        }
        return NO_POS;
    }

    Boolean isEmpty() const {
        return length() == 0;
    }

    CPtr toLowerCase() const {
        Size len = length();
        StringImpl* s = new StringImpl();
        for (Size i = 0; i < len; i++) {
            Char c = charAt(i);
            if (c >= 'A' && c <= 'Z')
                c += 'a' - 'A';
            s->str_ += c;
        }
        CPtr p(s);
        return p;
    }

    CPtr toUpperCase() const {
        Size len = length();
        StringImpl* s = new StringImpl();
        for (Size i = 0; i < len; i++) {
            Char c = charAt(i);
            if (c >= 'a' && c <= 'z')
                c -= 'a' - 'A';
            s->str_ += c;
        }
        CPtr p(s);
        return p;
    }

    CPtr toString() const {
        CPtr p(new StringImpl(*this));
        return p;
    }

    std::u16string toStdU16String() const {
        return glue::utf32ToUtf16(str_);
    }

    std::u32string toStdU32String() const {
        return str_;
    }

    std::string toStdString(Encoding enc) const {
        return glue::fromUtf32(str_, convertEncoding(enc));
    }

    static CPtr create() {
        CPtr p(new StringImpl());
        return p;
    }

    static CPtr create(Char c, Size n) {
        CPtr p(new StringImpl(c, n));
        return p;
    }

    static CPtr create(const std::u16string& s16) {
        CPtr p(new StringImpl(s16));
        return p;
    }

    static CPtr create(const std::u32string& s32) {
        CPtr p(new StringImpl(s32));
        return p;
    }

    static CPtr create(const void* data, Encoding enc, Size max) {
        CPtr p(new StringImpl(data, enc, max));
        return p;
    }

 private:
    static glue::UnicodeEncoding convertEncoding(Encoding enc) {
        switch (enc) {
        case UTF8:
            return glue::UTF8;
        case UTF16BE:
            return glue::UTF16BE;
        case UTF16LE:
            return glue::UTF16LE;
        case UTF32BE:
            return glue::UTF32BE;
        case UTF32LE:
            return glue::UTF32LE;
        default:
            assert(false);
        }
    }

 private:
    std::u32string str_;

    StringImpl() : str_() {}

    StringImpl(Char c, Size n) : str_(n, c) {}

    StringImpl(const std::u16string& s16)
        : str_(glue::utf16ToUtf32(s16)) {}

    StringImpl(const std::u32string& s32) : str_(s32) {}

    StringImpl(const void* data, Encoding enc, Size max)
        : str_(glue::toUtf32(data, convertEncoding(enc), max)) {}

    StringImpl(const StringImpl& other) : str_(other.str_) {}

    StringImpl(const StringImpl& other, Size pos, Size count = NO_POS)
        : str_(other.str_, pos, count) {}
};

String::CPtr String::create() {
    static const String::CPtr empty =
        StringImpl::create(NULL, UTF8, NO_POS);
    return empty;
}

String::CPtr String::create(Char c, Size n) {
    return StringImpl::create(c, n);
}

String::CPtr String::create(const std::u16string& s16) {
    return StringImpl::create(s16);
}

String::CPtr String::create(const std::u32string& s32) {
    return StringImpl::create(s32);
}

String::CPtr String::create(const void* data, Encoding enc, Size max) {
    return StringImpl::create(data, enc, max);
}

static String::CPtr LIBJ_STR_TRUE = String::create("true");
static String::CPtr LIBJ_STR_FALSE = String::create("false");

static String::CPtr booleanToString(const Value& val) {
    Boolean b;
    to<Boolean>(val, &b);
    return b ? LIBJ_STR_TRUE : LIBJ_STR_FALSE;
}

static String::CPtr byteToString(const Value& val) {
    Byte b;
    to<Byte>(val, &b);
    const Size kLen = (8 / 3) + 3;
    char s[kLen];
    snprintf(s, kLen, "%d", b);
    return String::create(s);
}

static String::CPtr shortToString(const Value& val) {
    Short sh;
    to<Short>(val, &sh);
    const Size kLen = (16 / 3) + 3;
    char s[kLen];
    snprintf(s, kLen, "%d", sh);
    return String::create(s);
}

static String::CPtr intToString(const Value& val) {
    Int i;
    to<Int>(val, &i);
    const Size kLen = (32 / 3) + 3;
    char s[kLen];
    snprintf(s, kLen, "%d", i);
    return String::create(s);
}

static String::CPtr longToString(const Value& val) {
    Long l;
    to<Long>(val, &l);
    const Size kLen = (64 / 3) + 3;
    char s[kLen];
    snprintf(s, kLen, "%lld", l);
    return String::create(s);
}

static String::CPtr floatToString(const Value& val) {
    Float f;
    to<Float>(val, &f);
    const Size kLen = 64;
    char s[kLen];
    return String::create(v8::internal::DoubleToCString(f, s, kLen));
}

static String::CPtr doubleToString(const Value& val) {
    Double d;
    to<Double>(val, &d);
    const Size kLen = 64;
    char s[kLen];
    return String::create(v8::internal::DoubleToCString(d, s, kLen));
}

static String::CPtr sizeToString(const Value& val) {
    Size n;
    to<Size>(val, &n);
    const Size kLen = ((sizeof(Size) << 3) / 3) + 3;
    char s[kLen];
    snprintf(s, kLen, "%zd", n);
    return String::create(s);
}

static String::CPtr typeIdToString(const Value& val) {
    TypeId t;
    to<TypeId>(val, &t);
    const Size kLen = ((sizeof(TypeId) << 3) / 3) + 3;
    char s[kLen];
    snprintf(s, kLen, "%zd", t);
    return String::create(s);
}

static String::CPtr objectToString(const Value& val) {
    Object::CPtr o = toCPtr<Object>(val);
    if (o) {
        return o->toString();
    } else {
        return String::null();
    }
}

String::CPtr String::valueOf(const Value& val) {
    if (val.isEmpty()) {
        return null();
    } else if (val.type() == Type<Boolean>::id()) {
        return booleanToString(val);
    } else if (val.type() == Type<Byte>::id()) {
        return byteToString(val);
    } else if (val.type() == Type<Short>::id()) {
        return shortToString(val);
    } else if (val.type() == Type<Int>::id()) {
        return intToString(val);
    } else if (val.type() == Type<Long>::id()) {
        return longToString(val);
    } else if (val.type() == Type<Float>::id()) {
        return floatToString(val);
    } else if (val.type() == Type<Double>::id()) {
        return doubleToString(val);
    } else if (val.type() == Type<Size>::id()) {
        return sizeToString(val);
    } else if (val.type() == Type<TypeId>::id()) {
        return typeIdToString(val);
    } else if (val.instanceof(Type<Object>::id())) {
        return objectToString(val);
    } else {
        return null();
    }
}

}  // namespace libj
<|endoftext|>


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

#include "ODDataBarCommon.h"

namespace ZXing {
namespace OneD {

// apparently the spec calls numbers at even indices 'odd'!?!
constexpr int odd = 0, evn = 1;

template <typename T>
struct OddEven
{
	T odd = {}, evn = {};
	T& operator[](int i) { return i & 1 ? evn : odd; }
};

bool ReadDataCharacterRaw(const PatternView& view, int numModules, bool reversed, Array4I& oddPattern,
						  Array4I& evnPattern)
{
	OddEven<Array4I&> res = {oddPattern, evnPattern};
	OddEven<Array4F> rem;

	float moduleSize = static_cast<float>(view.sum(8)) / numModules;
	auto* iter = view.data() + reversed * 7;
	int inc = reversed ? -1 : 1;

	for (int i = 0; i < 8; ++i, iter += inc) {
		float v = *iter / moduleSize;
		res[i % 2][i / 2] = int(v + .5f);
		rem[i % 2][i / 2] = v - res[i % 2][i / 2];
	}

	// DataBarExpanded data character is 17 modules wide
	// DataBar outer   data character is 16 modules wide
	// DataBar inner   data character is 15 modules wide

	int minSum = 4; // each data character has 4 bars and 4 spaces
	int maxSum = numModules - minSum;
	int oddSum = Reduce(res.odd);
	int evnSum = Reduce(res.evn);
	int sumErr = oddSum + evnSum - numModules;
	// sum < min -> negative error; sum > max -> positive error
	int oddSumErr = std::min(0, oddSum - (minSum + (numModules == 15))) + std::max(0, oddSum - maxSum);
	int evnSumErr = std::min(0, evnSum - minSum) + std::max(0, evnSum - (maxSum - (numModules == 15)));

	int oddParityErr = (oddSum & 1) == (numModules > 15);
	int evnParityErr = (evnSum & 1) == (numModules < 17);

	if ((sumErr == 0 && oddParityErr != evnParityErr) || (std::abs(sumErr) == 1 && oddParityErr == evnParityErr) ||
		std::abs(sumErr) > 1 || std::abs(oddSumErr) > 1 || std::abs(evnSumErr) > 1)
		return {};

	if (sumErr == -1) {
		oddParityErr *= -1;
		evnParityErr *= -1;
	} else if (sumErr == 0 && oddParityErr != 0) {
		// both parity errors are 1 -> flip one of them
		(oddSum < evnSum ? oddParityErr : evnParityErr) *= -1;
	}

	// check if parity and sum errors have opposite signs
	if (oddParityErr * oddSumErr < 0 || evnParityErr * evnSumErr < 0)
		return {};

	for (int i : {odd, evn}) {
		int err = i == odd ? (oddSumErr | oddParityErr) : (evnSumErr | evnParityErr);
		int mi = err > 0 ? std::max_element(rem[i].begin(), rem[i].end()) - rem[i].begin()
						 : std::min_element(rem[i].begin(), rem[i].end()) - rem[i].begin();
		res[i][mi] -= err;
	};

	return true;
}

} // OneD
} // ZXing
<commit_msg>DataBar: fix '<' vs '>' typo in ReadDataCharacterRaw error correction code<commit_after>/*
* Copyright 2020 Axel Waggershauser
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*      http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

#include "ODDataBarCommon.h"

namespace ZXing {
namespace OneD {

// apparently the spec calls numbers at even indices 'odd'!?!
constexpr int odd = 0, evn = 1;

template <typename T>
struct OddEven
{
	T odd = {}, evn = {};
	T& operator[](int i) { return i & 1 ? evn : odd; }
};

bool ReadDataCharacterRaw(const PatternView& view, int numModules, bool reversed, Array4I& oddPattern,
						  Array4I& evnPattern)
{
	OddEven<Array4I&> res = {oddPattern, evnPattern};
	OddEven<Array4F> rem;

	float moduleSize = static_cast<float>(view.sum(8)) / numModules;
	auto* iter = view.data() + reversed * 7;
	int inc = reversed ? -1 : 1;

	for (int i = 0; i < 8; ++i, iter += inc) {
		float v = *iter / moduleSize;
		res[i % 2][i / 2] = int(v + .5f);
		rem[i % 2][i / 2] = v - res[i % 2][i / 2];
	}

	// DataBarExpanded data character is 17 modules wide
	// DataBar outer   data character is 16 modules wide
	// DataBar inner   data character is 15 modules wide

	int minSum = 4; // each data character has 4 bars and 4 spaces
	int maxSum = numModules - minSum;
	int oddSum = Reduce(res.odd);
	int evnSum = Reduce(res.evn);
	int sumErr = oddSum + evnSum - numModules;
	// sum < min -> negative error; sum > max -> positive error
	int oddSumErr = std::min(0, oddSum - (minSum + (numModules == 15))) + std::max(0, oddSum - maxSum);
	int evnSumErr = std::min(0, evnSum - minSum) + std::max(0, evnSum - (maxSum - (numModules == 15)));

	int oddParityErr = (oddSum & 1) == (numModules > 15);
	int evnParityErr = (evnSum & 1) == (numModules < 17);

	if ((sumErr == 0 && oddParityErr != evnParityErr) || (std::abs(sumErr) == 1 && oddParityErr == evnParityErr) ||
		std::abs(sumErr) > 1 || std::abs(oddSumErr) > 1 || std::abs(evnSumErr) > 1)
		return {};

	if (sumErr == -1) {
		oddParityErr *= -1;
		evnParityErr *= -1;
	} else if (sumErr == 0 && oddParityErr != 0) {
		// both parity errors are 1 -> flip one of them
		(oddSum < evnSum ? oddParityErr : evnParityErr) *= -1;
	}

	// check if parity and sum errors have opposite signs
	if (oddParityErr * oddSumErr < 0 || evnParityErr * evnSumErr < 0)
		return {};

	for (int i : {odd, evn}) {
		int err = i == odd ? (oddSumErr | oddParityErr) : (evnSumErr | evnParityErr);
		int mi = err < 0 ? std::max_element(rem[i].begin(), rem[i].end()) - rem[i].begin()
						 : std::min_element(rem[i].begin(), rem[i].end()) - rem[i].begin();
		res[i][mi] -= err;
	};

	return true;
}

} // OneD
} // ZXing
<|endoftext|>