<commit_before>// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.

#include "common.h"

extern "C"
{
    void ThrowControlForThread(FaultingExceptionFrame *pfef)
    {
        PORTABILITY_ASSERT("Implement for PAL");
    }

    void NakedThrowHelper()
    {
        PORTABILITY_ASSERT("Implement for PAL");
    }

    void PInvokeStubForHost()
    {
        PORTABILITY_ASSERT("Implement for PAL");
    }

    void PInvokeStubForHostInner(DWORD dwStackSize, LPVOID pStackFrame, LPVOID pTarget)
    {
        PORTABILITY_ASSERT("Implement for PAL");
    }

    void ProfileEnterNaked(FunctionIDOrClientID functionIDOrClientID)
    {
        PORTABILITY_ASSERT("Implement for PAL");
    }

    void ProfileLeaveNaked(FunctionIDOrClientID functionIDOrClientID)
    {
        PORTABILITY_ASSERT("Implement for PAL");
    }

    void ProfileTailcallNaked(FunctionIDOrClientID functionIDOrClientID)
    {
        PORTABILITY_ASSERT("Implement for PAL");
    }

    void STDCALL JIT_ProfilerEnterLeaveTailcallStub(UINT_PTR ProfilerHandle)
    {
    }

    BOOL CallRtlUnwind()
    {
        PORTABILITY_ASSERT("CallRtlUnwind");
        return FALSE;
    }
};

VOID __cdecl PopSEHRecords(LPVOID pTargetSP)
{
    PORTABILITY_ASSERT("Implement for PAL");
}

EXTERN_C VOID BackPatchWorkerAsmStub()
{
    PORTABILITY_ASSERT("BackPatchWorkerAsmStub");
}

EXTERN_C VOID JIT_TailCall()
{
  PORTABILITY_ASSERT("JIT_TailCall");
}

EXTERN_C VOID JIT_TailCallReturnFromVSD()
{
  PORTABILITY_ASSERT("JIT_TailCallReturnFromVSD");
}

EXTERN_C VOID JIT_TailCallVSDLeave()
{
  PORTABILITY_ASSERT("JIT_TailCallVSDLeave");
}

EXTERN_C VOID JIT_TailCallLeave()
{
  PORTABILITY_ASSERT("JIT_TailCallLeave");
}

PTR_CONTEXT GetCONTEXTFromRedirectedStubStackFrame(T_DISPATCHER_CONTEXT * pDispatcherContext)
{
    PORTABILITY_ASSERT("GetCONTEXTFromRedirectedStubStackFrame");
    return NULL;
}

FaultingExceptionFrame *GetFrameFromRedirectedStubStackFrame(DISPATCHER_CONTEXT *pDispatcherContext)
{
    PORTABILITY_ASSERT("GetFrameFromRedirectedStubStackFrame");
    return NULL;
}
<commit_msg>[x86/Linux] Clean up CallRtlUnwind (#9813)<commit_after>// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.

#include "common.h"

extern "C"
{
    void ThrowControlForThread(FaultingExceptionFrame *pfef)
    {
        PORTABILITY_ASSERT("Implement for PAL");
    }

    void NakedThrowHelper()
    {
        PORTABILITY_ASSERT("Implement for PAL");
    }

    void PInvokeStubForHost()
    {
        PORTABILITY_ASSERT("Implement for PAL");
    }

    void PInvokeStubForHostInner(DWORD dwStackSize, LPVOID pStackFrame, LPVOID pTarget)
    {
        PORTABILITY_ASSERT("Implement for PAL");
    }

    void ProfileEnterNaked(FunctionIDOrClientID functionIDOrClientID)
    {
        PORTABILITY_ASSERT("Implement for PAL");
    }

    void ProfileLeaveNaked(FunctionIDOrClientID functionIDOrClientID)
    {
        PORTABILITY_ASSERT("Implement for PAL");
    }

    void ProfileTailcallNaked(FunctionIDOrClientID functionIDOrClientID)
    {
        PORTABILITY_ASSERT("Implement for PAL");
    }

    void STDCALL JIT_ProfilerEnterLeaveTailcallStub(UINT_PTR ProfilerHandle)
    {
    }
};

VOID __cdecl PopSEHRecords(LPVOID pTargetSP)
{
    PORTABILITY_ASSERT("Implement for PAL");
}

EXTERN_C VOID BackPatchWorkerAsmStub()
{
    PORTABILITY_ASSERT("BackPatchWorkerAsmStub");
}

EXTERN_C VOID JIT_TailCall()
{
  PORTABILITY_ASSERT("JIT_TailCall");
}

EXTERN_C VOID JIT_TailCallReturnFromVSD()
{
  PORTABILITY_ASSERT("JIT_TailCallReturnFromVSD");
}

EXTERN_C VOID JIT_TailCallVSDLeave()
{
  PORTABILITY_ASSERT("JIT_TailCallVSDLeave");
}

EXTERN_C VOID JIT_TailCallLeave()
{
  PORTABILITY_ASSERT("JIT_TailCallLeave");
}

PTR_CONTEXT GetCONTEXTFromRedirectedStubStackFrame(T_DISPATCHER_CONTEXT * pDispatcherContext)
{
    PORTABILITY_ASSERT("GetCONTEXTFromRedirectedStubStackFrame");
    return NULL;
}

FaultingExceptionFrame *GetFrameFromRedirectedStubStackFrame(DISPATCHER_CONTEXT *pDispatcherContext)
{
    PORTABILITY_ASSERT("GetFrameFromRedirectedStubStackFrame");
    return NULL;
}
<|endoftext|>


<commit_before>/* -*- mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- */

/*
 *  Main authors:
 *     Jip J. Dekker <jip@dekker.li>
 */

/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include <minizinc/presolve.hh>
#include <minizinc/astexception.hh>
#include <minizinc/astiterator.hh>
#include <minizinc/flatten.hh>
#include <minizinc/model.hh>
#include <minizinc/prettyprinter.hh>
#include <minizinc/typecheck.hh>

namespace MiniZinc {

  void Presolver::presolve() {
    find_presolve_annotations();
    if (submodels.size() < 1) return;

    find_presolved_calls();

    for (auto it = submodels.begin(); it != submodels.end(); ++it) {
//      TODO: Only when submodel has calls.
      switch (it->strategy) {
        case SubModel::GLOBAL:
          presolve_predicate_global(*it);
          break;
        default:
          throw EvalError(env.envi(), Location(), "Presolve strategy not supported yet.");
      }
    }
  }

  void Presolver::find_presolve_annotations() {
    class PresolveVisitor : public ItemVisitor {
    public:
      std::vector<SubModel>& submodels;
      EnvI& env;
      PresolveVisitor(EnvI& env, std::vector<SubModel>& submodels) : env(env), submodels(submodels) { };
      void vFunctionI(FunctionI* i) {
//        TODO: Check function type.
        Expression* ann = getAnnotation(i->ann(),constants().presolve.presolve);
        if (ann) {
          ASTExprVec<Expression> args = ann->cast<Call>()->args();
          Id* s_id = args[0]->cast<Id>();
          bool save = args[1]->cast<BoolLit>()->v();

          SubModel::Strategy strategy;
          if (s_id->v() == constants().presolve.calls->v())
            strategy = SubModel::CALLS;
          else if (s_id->v() == constants().presolve.model->v())
            strategy = SubModel::MODEL;
          else if (s_id->v() == constants().presolve.global->v())
            strategy = SubModel::GLOBAL;
          else
            throw TypeError(env, s_id->loc(), "Invalid presolve strategy `" + s_id->str().str() + "'");

          submodels.push_back(SubModel(i, strategy, save));
        }
      }
    } pv(env.envi(), submodels);
    iterItems(pv, model);
  }

  void Presolver::find_presolved_calls() {
    class CallSeeker : public ExprVisitor {
    public:
      std::vector<SubModel>& submodels;
      EnvI& env;
      Model* m;

      CallSeeker(std::vector<SubModel>& submodels, EnvI& env, Model* m) : submodels(submodels), env(env), m(m) { }
      virtual void vCall(Call &call) {
        for (size_t i = 0; i < submodels.size(); ++i) {
          if (submodels[i].predicate == m->matchFn(env, &call)) {
            submodels[i].addCall(&call);
          }
        }
      }
    } cf(submodels, env.envi(), model);
    TopDownIterator<CallSeeker> cf_it(cf);

    for (ConstraintIterator it = model->begin_constraints(); it != model->end_constraints(); ++it) {
      cf_it.run(it->e());
    }
  }

  void Presolver::presolve_predicate_global(SubModel& submodel) {
    assert(submodel.strategy == SubModel::Strategy::GLOBAL);

    submodel.predicate->ann().clear();

    GCLock lock;
    Model* m = new Model();
    Env e = Env(m);
    CopyMap cm;

    FunctionI* pred = copy(e.envi(), cm, submodel.predicate, true, true)->cast<FunctionI>();
    m->addItem(pred);
    m->registerFn(e.envi(),pred);
    std::vector<Expression*> args;
    for (auto it = submodel.predicate->params().begin(); it != submodel.predicate->params().end(); ++it) {
      //TODO: Deal with non-variable parameters
      VarDecl* vd = new VarDecl(Location(),
                                copy(e.envi(), cm, (*it)->ti(), true, true, false)->cast<TypeInst>(),
                                (*it)->id()->str().str(), NULL);
      m->addItem(new VarDeclI(Location(), vd));
      Id* arg = new Id(Location(), vd->id()->v(), vd);
      arg->type(vd->type());
      args.push_back(arg);
    }
    Call* pred_call = new Call(Location(), pred->id(), args);
    pred_call->type(Type::varbool());
    pred_call->decl(pred);
    ConstraintI* constraint = new ConstraintI(Location(), pred_call);
    m->addItem(constraint);
    m->addItem(SolveI::sat(Location()));

    model->mergeStdLib(e.envi(),m);

    FlatteningOptions fops = FlatteningOptions();
    // TODO: match main model.
    fops.onlyRangeDomains = false;
    flatten(e, fops);
//    Printer p = Printer(std::cerr);
//    std::cerr << std::endl << std::endl;
//    p.print(e.flat());
//    std::cerr << std::endl;

    delete m;
  }
}
<commit_msg>Fixes mismatch in submodel predicate arguments<commit_after>/* -*- mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- */

/*
 *  Main authors:
 *     Jip J. Dekker <jip@dekker.li>
 */

/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include <minizinc/presolve.hh>
#include <minizinc/astexception.hh>
#include <minizinc/astiterator.hh>
#include <minizinc/flatten.hh>
#include <minizinc/model.hh>
#include <minizinc/prettyprinter.hh>
#include <minizinc/typecheck.hh>

namespace MiniZinc {

  void Presolver::presolve() {
    find_presolve_annotations();
    if (submodels.size() < 1) return;

    find_presolved_calls();

    for (auto it = submodels.begin(); it != submodels.end(); ++it) {
//      TODO: Only when submodel has calls.
      switch (it->strategy) {
        case SubModel::GLOBAL:
          presolve_predicate_global(*it);
          break;
        default:
          throw EvalError(env.envi(), Location(), "Presolve strategy not supported yet.");
      }
    }
  }

  void Presolver::find_presolve_annotations() {
    class PresolveVisitor : public ItemVisitor {
    public:
      std::vector<SubModel>& submodels;
      EnvI& env;
      PresolveVisitor(EnvI& env, std::vector<SubModel>& submodels) : env(env), submodels(submodels) { };
      void vFunctionI(FunctionI* i) {
//        TODO: Check function type.
        Expression* ann = getAnnotation(i->ann(),constants().presolve.presolve);
        if (ann) {
          ASTExprVec<Expression> args = ann->cast<Call>()->args();
          Id* s_id = args[0]->cast<Id>();
          bool save = args[1]->cast<BoolLit>()->v();

          SubModel::Strategy strategy;
          if (s_id->v() == constants().presolve.calls->v())
            strategy = SubModel::CALLS;
          else if (s_id->v() == constants().presolve.model->v())
            strategy = SubModel::MODEL;
          else if (s_id->v() == constants().presolve.global->v())
            strategy = SubModel::GLOBAL;
          else
            throw TypeError(env, s_id->loc(), "Invalid presolve strategy `" + s_id->str().str() + "'");

          submodels.push_back(SubModel(i, strategy, save));
        }
      }
    } pv(env.envi(), submodels);
    iterItems(pv, model);
  }

  void Presolver::find_presolved_calls() {
    class CallSeeker : public ExprVisitor {
    public:
      std::vector<SubModel>& submodels;
      EnvI& env;
      Model* m;

      CallSeeker(std::vector<SubModel>& submodels, EnvI& env, Model* m) : submodels(submodels), env(env), m(m) { }
      virtual void vCall(Call &call) {
        for (size_t i = 0; i < submodels.size(); ++i) {
          if (submodels[i].predicate == m->matchFn(env, &call)) {
            submodels[i].addCall(&call);
          }
        }
      }
    } cf(submodels, env.envi(), model);
    TopDownIterator<CallSeeker> cf_it(cf);

    for (ConstraintIterator it = model->begin_constraints(); it != model->end_constraints(); ++it) {
      cf_it.run(it->e());
    }
  }

  void Presolver::presolve_predicate_global(SubModel& submodel) {
    assert(submodel.strategy == SubModel::Strategy::GLOBAL);

    submodel.predicate->ann().clear();

    GCLock lock;
    Model* m = new Model();
    Env e = Env(m);
    CopyMap cm;

    FunctionI* pred = copy(e.envi(), cm, submodel.predicate, false, true)->cast<FunctionI>();
    m->addItem(pred);
    m->registerFn(e.envi(), pred);
    std::vector<Expression*> args;
    for (auto it = pred->params().begin(); it != pred->params().end(); ++it) {
      //TODO: Deal with non-variable parameters
      VarDecl* vd = new VarDecl(Location(), (*it)->ti(), (*it)->id(), NULL);
      m->addItem(new VarDeclI(Location(), vd));
      Id* arg = new Id(Location(), vd->id()->str().str(), vd);
      arg->type(vd->type());
      args.push_back(arg);
    }
    Call* pred_call = new Call(Location(), pred->id().str(), args, pred);
    pred_call->type(Type::varbool());
    ConstraintI* constraint = new ConstraintI(Location(), pred_call);
    m->addItem(constraint);
    m->addItem(SolveI::sat(Location()));

    model->mergeStdLib(e.envi(),m);

    FlatteningOptions fops = FlatteningOptions();
    // TODO: match main model.
    fops.onlyRangeDomains = false;
    flatten(e, fops);

//    Printer p = Printer(std::cerr);
//    std::cerr << std::endl << std::endl;
//    p.print(e.flat());
//    std::cerr << std::endl;

    delete m;
  }
}
<|endoftext|>


<commit_before>#pragma once

#include <ostream>
#include <string>

#include <boost/algorithm/string.hpp>
#include <boost/variant.hpp>

#include "blackhole/detail/stream/stream.hpp"
#include "blackhole/error.hpp"
#include "blackhole/formatter/map/value.hpp"
#include "blackhole/formatter/string/parser.hpp"
#include "blackhole/record.hpp"

namespace blackhole {

namespace formatter {

namespace string {

class variadic_visitor_t : public boost::static_visitor<> {
    const attribute::name_t& name;
    const attribute::value_t& value;
    std::ostringstream& stream;

public:
    variadic_visitor_t(const attribute::name_t& name,
                       const attribute::value_t& value,
                       std::ostringstream& stream) :
        name(name),
        value(value),
        stream(stream)
    {}

    void operator()(const literal_t& literal) {
        stream << literal.value;
    }

    void operator()(const placeholder::variadic_t::key_t&) {
        stream << name;
    }

    void operator()(const placeholder::variadic_t::value_t) {
        stream << value;
    }
};

class visitor_t : public boost::static_visitor<> {
    stickystream_t& stream;
    const mapping::value_t& mapper;
    const attribute::set_view_t& view;

public:
    visitor_t(stickystream_t& stream,
              const mapping::value_t& mapper,
              const attribute::set_view_t& view) :
        stream(stream),
        mapper(mapper),
        view(view)
    {}

    void operator()(const literal_t& literal) {
        stream.rdbuf()->storage()->append(literal.value);
    }

    void operator()(const placeholder::required_t& ph) {
        if (auto attribute = view.find(ph.name)) {
            mapper(stream, ph.name, attribute->value);
            return;
        }

        throw error_t("required attribute '%s' was not provided", ph.name);
    }

    void operator()(const placeholder::optional_t& ph) {
        if (auto attribute = view.find(ph.name)) {
            stream.rdbuf()->storage()->append(ph.prefix);
            mapper(stream, ph.name, attribute->value);
            stream.rdbuf()->storage()->append(ph.suffix);
        }
    }

    //!@todo: 1. Test pattern.
    void operator()(const placeholder::variadic_t& ph) {
        std::vector<std::string> passed;
        passed.reserve(view.upper_size());

        //!@todo: 3. Call begin() & end() with parameter.
        for (auto it = view.begin(); it != view.end(); ++it) {
            //!@todo: 2. This code needs some optimization love.
            std::ostringstream stream;
            variadic_visitor_t visitor(it->first, it->second.value, stream);
            for (auto t = ph.pattern.begin(); t != ph.pattern.end(); ++t) {
                boost::apply_visitor(visitor, *t);
            }

            passed.push_back(stream.str());
        }

        if (!passed.empty()) {
            stream.rdbuf()->storage()->append(ph.prefix);
            stream.rdbuf()->storage()->append(
                boost::algorithm::join(passed, ph.separator)
            );
            stream.rdbuf()->storage()->append(ph.suffix);
        }
    }
};

} // namespace string

} // namespace formatter

} // namespace blackhole
<commit_msg>[Tasks] One task less.<commit_after>#pragma once

#include <ostream>
#include <string>

#include <boost/algorithm/string.hpp>
#include <boost/variant.hpp>

#include "blackhole/detail/stream/stream.hpp"
#include "blackhole/error.hpp"
#include "blackhole/formatter/map/value.hpp"
#include "blackhole/formatter/string/parser.hpp"
#include "blackhole/record.hpp"

namespace blackhole {

namespace formatter {

namespace string {

class variadic_visitor_t : public boost::static_visitor<> {
    const attribute::name_t& name;
    const attribute::value_t& value;
    std::ostringstream& stream;

public:
    variadic_visitor_t(const attribute::name_t& name,
                       const attribute::value_t& value,
                       std::ostringstream& stream) :
        name(name),
        value(value),
        stream(stream)
    {}

    void operator()(const literal_t& literal) {
        stream << literal.value;
    }

    void operator()(const placeholder::variadic_t::key_t&) {
        stream << name;
    }

    void operator()(const placeholder::variadic_t::value_t) {
        stream << value;
    }
};

class visitor_t : public boost::static_visitor<> {
    stickystream_t& stream;
    const mapping::value_t& mapper;
    const attribute::set_view_t& view;

public:
    visitor_t(stickystream_t& stream,
              const mapping::value_t& mapper,
              const attribute::set_view_t& view) :
        stream(stream),
        mapper(mapper),
        view(view)
    {}

    void operator()(const literal_t& literal) {
        stream.rdbuf()->storage()->append(literal.value);
    }

    void operator()(const placeholder::required_t& ph) {
        if (auto attribute = view.find(ph.name)) {
            mapper(stream, ph.name, attribute->value);
            return;
        }

        throw error_t("required attribute '%s' was not provided", ph.name);
    }

    void operator()(const placeholder::optional_t& ph) {
        if (auto attribute = view.find(ph.name)) {
            stream.rdbuf()->storage()->append(ph.prefix);
            mapper(stream, ph.name, attribute->value);
            stream.rdbuf()->storage()->append(ph.suffix);
        }
    }

    void operator()(const placeholder::variadic_t& ph) {
        std::vector<std::string> passed;
        passed.reserve(view.upper_size());

        //!@todo: 3. Call begin() & end() with parameter.
        for (auto it = view.begin(); it != view.end(); ++it) {
            //!@todo: 2. This code needs some optimization love.
            std::ostringstream stream;
            variadic_visitor_t visitor(it->first, it->second.value, stream);
            for (auto t = ph.pattern.begin(); t != ph.pattern.end(); ++t) {
                boost::apply_visitor(visitor, *t);
            }

            passed.push_back(stream.str());
        }

        if (!passed.empty()) {
            stream.rdbuf()->storage()->append(ph.prefix);
            stream.rdbuf()->storage()->append(
                boost::algorithm::join(passed, ph.separator)
            );
            stream.rdbuf()->storage()->append(ph.suffix);
        }
    }
};

} // namespace string

} // namespace formatter

} // namespace blackhole
<|endoftext|>


<commit_before>/*
 *  FileSystem.cc
 *  Apto
 *
 *  Created by David on 12/7/05.
 *  Copyright 2005-2011 David Michael Bryson. All rights reserved.
 *  http://programerror.com/software/apto
 *
 *  Redistribution and use in source and binary forms, with or without modification, are permitted provided that the
 *  following conditions are met:
 *
 *  1.  Redistributions of source code must retain the above copyright notice, this list of conditions and the
 *      following disclaimer.
 *  2.  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.
 *  3.  Neither the name of David Michael Bryson, nor the names of contributors may be used to endorse or promote
 *      products derived from this software without specific prior written permission.
 *
 *  THIS SOFTWARE IS PROVIDED BY DAVID MICHAEL BRYSON 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 DAVID MICHAEL BRYSON 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.
 *
 *  Authors: David M. Bryson <david@programerror.com>
 *
 */

#include "apto/core/FileSystem.h"

#include "apto/platform/Platform.h"
#include "apto/platform/FileSystem.h"

#include <cerrno>
#include <sys/stat.h>
#include <cstdio>
#include <fstream>

// mkdir undefined in ms windows
#if APTO_PLATFORM(WINDOWS)
# include <direct.h>
# ifndef ACCESSPERMS
#  define ACCESSPERMS 0
# endif
# ifndef mkdir
#  define mkdir(path, ignored_mode) _mkdir(path)
# endif
# ifndef chdir
#  define chdir(path) _chdir(path)
# endif
# ifndef mode_t
#  define mode_t unsigned int
# endif
#endif

#if APTO_PLATFORM(WINDOWS)
# include <direct.h>
#else
# include <unistd.h>
#endif

namespace Apto {
  namespace FileSystem {

    String GetCWD()
    {
      String cwd_str;

      char* dirbuf = new char[MAXIMUM_DIRECTORY_LENGTH];
#if APTO_PLATFORM(WINDOWS)
      char* cwd = _getcwd(dirbuf, MAXIMUM_DIRECTORY_LENGTH);
#else
      char* cwd = getcwd(dirbuf, MAXIMUM_DIRECTORY_LENGTH);
#endif
      if (cwd != NULL) cwd_str = cwd;
      delete [] dirbuf;

      return cwd_str;
    }

    String GetAbsolutePath(const String& path, const String& working_dir)
    {
      if (path.GetSize() == 0) return working_dir;

#if APTO_PLATFORM(WINDOWS)
      if (!(path.IsLetter(0) && path[1] == ':' && path[2] =='\\')) return PathAppend(working_dir, path);
#else
      if (path[0] != '/' && path[0] != '\\') return PathAppend(working_dir, path);
#endif

      return path;
    }

    bool ChDir(const String& path)
    {
      if (!IsDir(path))
        return false;
      return chdir(path);
    }

    bool IsDir(const String& path)
    {
      struct stat st;
      if (stat(path, &st) == 0 && st.st_mode & S_IFDIR) return true;
      return false;
    }

    bool IsFile(const String& path)
    {
      struct stat st;
      if (stat(path, &st) == 0 && st.st_mode & S_IFREG) return true;
      return false;
    }

    bool CpDir(const String& src, const String& dest)
    {
      if (!IsDir(src)) return false;

      MkDir(dest);

      // Collect entries in directory
      Array<String, Smart> direntries;
      ReadDir(src, direntries);

      // Process all entries, removing them as appropriate
      for (int i = 0; i < direntries.GetSize(); i++) {
        // Do not copy current or parent directory entries
        if (direntries[i] == "." || direntries[i] == "..") continue;

        Apto::String src_path = PathAppend(src, direntries[i]);
        Apto::String dest_path = PathAppend(dest, direntries[i]);

        struct stat st;
        if (stat(src_path, &st) != 0) continue;

        if (st.st_mode & S_IFDIR) {
          // Recursively copy subdirectory
          if (!CpDir(src_path, dest_path)) return false;
        } else if (st.st_mode & S_IFREG) {
          // Cop regular file
          if (!CpFile(src_path, dest_path)) return false;
        }
      }

      return true;
    }

    bool MkDir(const String& dirname)
    {
      FILE* fp = 0;

#if APTO_PLATFORM(WINDOWS)
      fopen_s(&fp, dirname, "r");
      if (fp == 0) {
#else
      fp = fopen(dirname, "r");
      if (fp == 0) {
#endif
        if (errno == ENOENT) {
          // not found, creating...
          if (mkdir(dirname, (S_IRWXU | S_IRWXG | S_IRWXO))) return false;

          return true;
        }

        return false;
      }
      fclose(fp);

      // found
      return true;
    }

    bool RmDir(const String& dirname, bool recursive)
    {
      if (!IsDir(dirname)) return false;

      if (recursive) {
        // Collect entries in directory
        Array<String, Smart> direntries;
        ReadDir(dirname, direntries);

        // Process all entries, removing them as appropriate
        for (int i = 0; i < direntries.GetSize(); i++) {
          // Do not remove current or parent directory entries
          if (direntries[i] == "." || direntries[i] == "..") continue;

          Apto::String path = PathAppend(dirname, direntries[i]);

          struct stat st;
          if (stat(path, &st) != 0) continue;

          if (st.st_mode & S_IFDIR) {
            // Recursively remove subdirectory
            if (!RmDir(path)) return false;
          } else {
            // Remove regular (or other) file
            if (remove(path) != 0) return false;
          }
        }
      }

      // Attempt to remove the directory itself
#if APTO_PLATFORM(WINDOWS)
      return (_rmdir(dirname) == 0);
#else
      return (rmdir(dirname) == 0);
#endif
    }

    bool ReadDir(const String& path, Array<String, Smart>& entries)
    {
      DIR* dp;
      struct dirent* dirp;
      if ((dp = opendir(path)) == NULL) return false;

      while ((dirp = readdir(dp)) != NULL) entries.Push(dirp->d_name);

      closedir(dp);
      return true;
    }

    bool CpFile(const String& src, const String& dest)
    {
      std::ifstream ifs(src, std::ios::binary);
      std::ofstream ofs(dest, std::ios::binary);

      if (!ifs.is_open() || !ofs.is_open()) return false;

      ofs << ifs.rdbuf();

      ifs.close();
      ofs.close();

      return true;
    }

    bool RmFile(const String& path)
    {
      return (remove(path) == 0);
    }

  };
};
<commit_msg>Added chdir functionality.<commit_after>/*
 *  FileSystem.cc
 *  Apto
 *
 *  Created by David on 12/7/05.
 *  Copyright 2005-2011 David Michael Bryson. All rights reserved.
 *  http://programerror.com/software/apto
 *
 *  Redistribution and use in source and binary forms, with or without modification, are permitted provided that the
 *  following conditions are met:
 *
 *  1.  Redistributions of source code must retain the above copyright notice, this list of conditions and the
 *      following disclaimer.
 *  2.  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.
 *  3.  Neither the name of David Michael Bryson, nor the names of contributors may be used to endorse or promote
 *      products derived from this software without specific prior written permission.
 *
 *  THIS SOFTWARE IS PROVIDED BY DAVID MICHAEL BRYSON 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 DAVID MICHAEL BRYSON 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.
 *
 *  Authors: David M. Bryson <david@programerror.com>
 *
 */

#include "apto/core/FileSystem.h"

#include "apto/platform/Platform.h"
#include "apto/platform/FileSystem.h"

#include <cerrno>
#include <sys/stat.h>
#include <cstdio>
#include <fstream>

// mkdir undefined in ms windows
#if APTO_PLATFORM(WINDOWS)
# include <direct.h>
# ifndef ACCESSPERMS
#  define ACCESSPERMS 0
# endif
# ifndef mkdir
#  define mkdir(path, ignored_mode) _mkdir(path)
# endif
# ifndef chdir
#  define chdir(path) _chdir(path)
# endif
# ifndef mode_t
#  define mode_t unsigned int
# endif
#endif

#if APTO_PLATFORM(WINDOWS)
# include <direct.h>
#else
# include <unistd.h>
#endif

namespace Apto {
  namespace FileSystem {

    String GetCWD()
    {
      String cwd_str;

      char* dirbuf = new char[MAXIMUM_DIRECTORY_LENGTH];
#if APTO_PLATFORM(WINDOWS)
      char* cwd = _getcwd(dirbuf, MAXIMUM_DIRECTORY_LENGTH);
#else
      char* cwd = getcwd(dirbuf, MAXIMUM_DIRECTORY_LENGTH);
#endif
      if (cwd != NULL) cwd_str = cwd;
      delete [] dirbuf;

      return cwd_str;
    }

    String GetAbsolutePath(const String& path, const String& working_dir)
    {
      if (path.GetSize() == 0) return working_dir;

#if APTO_PLATFORM(WINDOWS)
      if (!(path.IsLetter(0) && path[1] == ':' && path[2] =='\\')) return PathAppend(working_dir, path);
#else
      if (path[0] != '/' && path[0] != '\\') return PathAppend(working_dir, path);
#endif

      return path;
    }

    bool ChDir(const String& path)
    {
      if (!IsDir(path))
        return false;
      return (chdir(path) == 0);
    }

    bool IsDir(const String& path)
    {
      struct stat st;
      if (stat(path, &st) == 0 && st.st_mode & S_IFDIR) return true;
      return false;
    }

    bool IsFile(const String& path)
    {
      struct stat st;
      if (stat(path, &st) == 0 && st.st_mode & S_IFREG) return true;
      return false;
    }

    bool CpDir(const String& src, const String& dest)
    {
      if (!IsDir(src)) return false;

      MkDir(dest);

      // Collect entries in directory
      Array<String, Smart> direntries;
      ReadDir(src, direntries);

      // Process all entries, removing them as appropriate
      for (int i = 0; i < direntries.GetSize(); i++) {
        // Do not copy current or parent directory entries
        if (direntries[i] == "." || direntries[i] == "..") continue;

        Apto::String src_path = PathAppend(src, direntries[i]);
        Apto::String dest_path = PathAppend(dest, direntries[i]);

        struct stat st;
        if (stat(src_path, &st) != 0) continue;

        if (st.st_mode & S_IFDIR) {
          // Recursively copy subdirectory
          if (!CpDir(src_path, dest_path)) return false;
        } else if (st.st_mode & S_IFREG) {
          // Cop regular file
          if (!CpFile(src_path, dest_path)) return false;
        }
      }

      return true;
    }

    bool MkDir(const String& dirname)
    {
      FILE* fp = 0;

#if APTO_PLATFORM(WINDOWS)
      fopen_s(&fp, dirname, "r");
      if (fp == 0) {
#else
      fp = fopen(dirname, "r");
      if (fp == 0) {
#endif
        if (errno == ENOENT) {
          // not found, creating...
          if (mkdir(dirname, (S_IRWXU | S_IRWXG | S_IRWXO))) return false;

          return true;
        }

        return false;
      }
      fclose(fp);

      // found
      return true;
    }

    bool RmDir(const String& dirname, bool recursive)
    {
      if (!IsDir(dirname)) return false;

      if (recursive) {
        // Collect entries in directory
        Array<String, Smart> direntries;
        ReadDir(dirname, direntries);

        // Process all entries, removing them as appropriate
        for (int i = 0; i < direntries.GetSize(); i++) {
          // Do not remove current or parent directory entries
          if (direntries[i] == "." || direntries[i] == "..") continue;

          Apto::String path = PathAppend(dirname, direntries[i]);

          struct stat st;
          if (stat(path, &st) != 0) continue;

          if (st.st_mode & S_IFDIR) {
            // Recursively remove subdirectory
            if (!RmDir(path)) return false;
          } else {
            // Remove regular (or other) file
            if (remove(path) != 0) return false;
          }
        }
      }

      // Attempt to remove the directory itself
#if APTO_PLATFORM(WINDOWS)
      return (_rmdir(dirname) == 0);
#else
      return (rmdir(dirname) == 0);
#endif
    }

    bool ReadDir(const String& path, Array<String, Smart>& entries)
    {
      DIR* dp;
      struct dirent* dirp;
      if ((dp = opendir(path)) == NULL) return false;

      while ((dirp = readdir(dp)) != NULL) entries.Push(dirp->d_name);

      closedir(dp);
      return true;
    }

    bool CpFile(const String& src, const String& dest)
    {
      std::ifstream ifs(src, std::ios::binary);
      std::ofstream ofs(dest, std::ios::binary);

      if (!ifs.is_open() || !ofs.is_open()) return false;

      ofs << ifs.rdbuf();

      ifs.close();
      ofs.close();

      return true;
    }

    bool RmFile(const String& path)
    {
      return (remove(path) == 0);
    }

  };
};
<|endoftext|>


<commit_before>/*****************************************************************************
 *
 * This file is part of Mapnik (c++ mapping toolkit)
 *
 * Copyright (C) 2006 Artem Pavlenko, Jean-Francois Doyon
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 *
 *****************************************************************************/
//$Id$

// boost
#include <boost/python/suite/indexing/indexing_suite.hpp>
#include <boost/python/iterator.hpp>
#include <boost/python/call_method.hpp>
#include <boost/python/tuple.hpp>
#include <boost/python.hpp>
#include <boost/scoped_array.hpp>
// mapnik
#include <mapnik/feature.hpp>
#include <mapnik/datasource.hpp>
#include <mapnik/wkb.hpp>

mapnik::geometry2d & (mapnik::Feature::*get_geom1)(unsigned) = &mapnik::Feature::get_geometry;

namespace {

using mapnik::Feature;
using mapnik::geometry_utils;

void feature_add_wkb_geometry(Feature &feature, std::string wkb)
{
    geometry_utils::from_wkb(feature, wkb.c_str(), wkb.size(), true);
}

} // end anonymous namespace

namespace boost { namespace python {
struct value_converter : public boost::static_visitor<PyObject*>
{
    PyObject * operator() (int val) const
    {
	return ::PyInt_FromLong(val);
    }

    PyObject * operator() (double val) const
    {
	return ::PyFloat_FromDouble(val);
    }

    PyObject * operator() (UnicodeString const& s) const
    {
	std::string buffer;
	mapnik::to_utf8(s,buffer);
	PyObject *obj = Py_None;
	obj = ::PyUnicode_DecodeUTF8(buffer.c_str(),implicit_cast<ssize_t>(buffer.length()),0);
	return obj;
    }

    PyObject * operator() (mapnik::value_null const& s) const
    {
	return NULL;
    }
};

struct mapnik_value_to_python
{
    static PyObject* convert(mapnik::value const& v)
    {
	return boost::apply_visitor(value_converter(),v.base());
    }
};

// Forward declaration
template <class Container, bool NoProxy, class DerivedPolicies>
class map_indexing_suite2;

namespace detail
{
template <class Container, bool NoProxy>
class final_map_derived_policies
    : public map_indexing_suite2<Container,
				 NoProxy, final_map_derived_policies<Container, NoProxy> > {};
}

template <
class Container,
bool NoProxy = false,
class DerivedPolicies
= detail::final_map_derived_policies<Container, NoProxy> >
class map_indexing_suite2
    : public indexing_suite<
Container
, DerivedPolicies
, NoProxy
, true
, typename Container::value_type::second_type
, typename Container::key_type
, typename Container::key_type
>
{
public:

    typedef typename Container::value_type value_type;
    typedef typename Container::value_type::second_type data_type;
    typedef typename Container::key_type key_type;
    typedef typename Container::key_type index_type;
    typedef typename Container::size_type size_type;
    typedef typename Container::difference_type difference_type;

    template <class Class>
    static void
    extension_def(Class& cl)
    {

    }

    static data_type&
    get_item(Container& container, index_type i_)
    {
	typename Container::iterator i = container.props().find(i_);
	if (i == container.end())
	{
	    PyErr_SetString(PyExc_KeyError, "Invalid key");
	    throw_error_already_set();
	}
	return i->second;
    }

    static void
    set_item(Container& container, index_type i, data_type const& v)
    {
	container[i] = v;
    }

    static void
    delete_item(Container& container, index_type i)
    {
	container.props().erase(i);
    }

    static size_t
    size(Container& container)
    {
	return container.props().size();
    }

    static bool
    contains(Container& container, key_type const& key)
    {
	return container.props().find(key) != container.end();
    }

    static bool
    compare_index(Container& container, index_type a, index_type b)
    {
	return container.props().key_comp()(a, b);
    }

    static index_type
    convert_index(Container& /*container*/, PyObject* i_)
    {
	extract<key_type const&> i(i_);
	if (i.check())
	{
	    return i();
	}
	else
	{
	    extract<key_type> i(i_);
	    if (i.check())
		return i();
	}

	PyErr_SetString(PyExc_TypeError, "Invalid index type");
	throw_error_already_set();
	return index_type();
    }
};

template <typename T1, typename T2>
struct std_pair_to_tuple
{
    static PyObject* convert(std::pair<T1, T2> const& p)
    {
	return boost::python::incref(
	    boost::python::make_tuple(p.first, p.second).ptr());
    }
};

template <typename T1, typename T2>
struct std_pair_to_python_converter
{
    std_pair_to_python_converter()
    {
	boost::python::to_python_converter<
	std::pair<T1, T2>,
	    std_pair_to_tuple<T1, T2> >();
    }
};

}}

struct UnicodeString_from_python_str
{
    UnicodeString_from_python_str()
    {
        boost::python::converter::registry::push_back(
            &convertible,
            &construct,
            boost::python::type_id<UnicodeString>());
    }

    static void* convertible(PyObject* obj_ptr)
    {
        if (!(PyString_Check(obj_ptr) || PyUnicode_Check(obj_ptr)))
            return 0;
        return obj_ptr;
    }

    static void construct(
        PyObject* obj_ptr,
        boost::python::converter::rvalue_from_python_stage1_data* data)
    {
        char * value=0;
        if (PyUnicode_Check(obj_ptr)) {
            PyObject *encoded = PyUnicode_AsEncodedString(obj_ptr, "utf8", "replace");
            if (encoded) {
                value = PyString_AsString(encoded);
                Py_DecRef(encoded);
            }
        } else {
            value = PyString_AsString(obj_ptr);
        }
        if (value == 0) boost::python::throw_error_already_set();
        void* storage = (
            (boost::python::converter::rvalue_from_python_storage<UnicodeString>*)
            data)->storage.bytes;
        new (storage) UnicodeString(value);
        data->convertible = storage;
    }
};

void export_feature()
{
    using namespace boost::python;
    using mapnik::Feature;

    implicitly_convertible<int,mapnik::value>();
    implicitly_convertible<double,mapnik::value>();
    implicitly_convertible<UnicodeString,mapnik::value>();
    implicitly_convertible<bool,mapnik::value>();

    std_pair_to_python_converter<std::string const,mapnik::value>();
    to_python_converter<mapnik::value,mapnik_value_to_python>();
    UnicodeString_from_python_str();

    class_<Feature,boost::shared_ptr<Feature>,
	boost::noncopyable>("Feature",init<int>("Default ctor."))
	.def("id",&Feature::id)
	.def("__str__",&Feature::to_string)
	.def("add_geometry", &feature_add_wkb_geometry)
	.def("num_geometries",&Feature::num_geometries)
	.def("get_geometry", make_function(get_geom1,return_value_policy<reference_existing_object>()))
	.def("envelope", &Feature::envelope)
	.def(map_indexing_suite2<Feature, true >())
	.def("iteritems",iterator<Feature> ())
        // TODO define more mapnik::Feature methods
	;
}
<commit_msg>+ more tidy<commit_after>/*****************************************************************************
 *
 * This file is part of Mapnik (c++ mapping toolkit)
 *
 * Copyright (C) 2006 Artem Pavlenko, Jean-Francois Doyon
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 *
 *****************************************************************************/
//$Id$

// boost
#include <boost/python/suite/indexing/indexing_suite.hpp>
#include <boost/python/iterator.hpp>
#include <boost/python/call_method.hpp>
#include <boost/python/tuple.hpp>
#include <boost/python.hpp>
#include <boost/scoped_array.hpp>
// mapnik
#include <mapnik/feature.hpp>
#include <mapnik/datasource.hpp>
#include <mapnik/wkb.hpp>

mapnik::geometry2d & (mapnik::Feature::*get_geom1)(unsigned) = &mapnik::Feature::get_geometry;

namespace {

using mapnik::Feature;
using mapnik::geometry_utils;

void feature_add_wkb_geometry(Feature &feature, std::string wkb)
{
    geometry_utils::from_wkb(feature, wkb.c_str(), wkb.size(), true);
}

} // end anonymous namespace

namespace boost { namespace python {
struct value_converter : public boost::static_visitor<PyObject*>
{
    PyObject * operator() (int val) const
    {
	return ::PyInt_FromLong(val);
    }

    PyObject * operator() (double val) const
    {
	return ::PyFloat_FromDouble(val);
    }

    PyObject * operator() (UnicodeString const& s) const
    {
	std::string buffer;
	mapnik::to_utf8(s,buffer);
	PyObject *obj = Py_None;
	obj = ::PyUnicode_DecodeUTF8(buffer.c_str(),implicit_cast<ssize_t>(buffer.length()),0);
	return obj;
    }

    PyObject * operator() (mapnik::value_null const& s) const
    {
	return NULL;
    }
};

struct mapnik_value_to_python
{
    static PyObject* convert(mapnik::value const& v)
    {
	return boost::apply_visitor(value_converter(),v.base());
    }
};

// Forward declaration
template <class Container, bool NoProxy, class DerivedPolicies>
class map_indexing_suite2;

namespace detail
{
template <class Container, bool NoProxy>
class final_map_derived_policies
    : public map_indexing_suite2<Container,
				 NoProxy, final_map_derived_policies<Container, NoProxy> > {};
}

template <class Container,bool NoProxy = false,
class DerivedPolicies = detail::final_map_derived_policies<Container, NoProxy> >
class map_indexing_suite2
    : public indexing_suite<
Container
, DerivedPolicies
, NoProxy
, true
, typename Container::value_type::second_type
, typename Container::key_type
, typename Container::key_type
>
{
public:

    typedef typename Container::value_type value_type;
    typedef typename Container::value_type::second_type data_type;
    typedef typename Container::key_type key_type;
    typedef typename Container::key_type index_type;
    typedef typename Container::size_type size_type;
    typedef typename Container::difference_type difference_type;

    template <class Class>
    static void
    extension_def(Class& cl)
    {

    }

    static data_type&
    get_item(Container& container, index_type i_)
    {
	typename Container::iterator i = container.props().find(i_);
	if (i == container.end())
	{
	    PyErr_SetString(PyExc_KeyError, "Invalid key");
	    throw_error_already_set();
	}
	return i->second;
    }

    static void
    set_item(Container& container, index_type i, data_type const& v)
    {
	container[i] = v;
    }

    static void
    delete_item(Container& container, index_type i)
    {
	container.props().erase(i);
    }

    static size_t
    size(Container& container)
    {
	return container.props().size();
    }

    static bool
    contains(Container& container, key_type const& key)
    {
	return container.props().find(key) != container.end();
    }

    static bool
    compare_index(Container& container, index_type a, index_type b)
    {
	return container.props().key_comp()(a, b);
    }

    static index_type
    convert_index(Container& /*container*/, PyObject* i_)
    {
	extract<key_type const&> i(i_);
	if (i.check())
	{
	    return i();
	}
	else
	{
	    extract<key_type> i(i_);
	    if (i.check())
		return i();
	}

	PyErr_SetString(PyExc_TypeError, "Invalid index type");
	throw_error_already_set();
	return index_type();
    }
};

template <typename T1, typename T2>
struct std_pair_to_tuple
{
    static PyObject* convert(std::pair<T1, T2> const& p)
    {
	return boost::python::incref(
	    boost::python::make_tuple(p.first, p.second).ptr());
    }
};

template <typename T1, typename T2>
struct std_pair_to_python_converter
{
    std_pair_to_python_converter()
    {
	boost::python::to_python_converter<
	std::pair<T1, T2>,
	std_pair_to_tuple<T1, T2> >();
    }
};

}}

struct UnicodeString_from_python_str
{
    UnicodeString_from_python_str()
    {
        boost::python::converter::registry::push_back(
            &convertible,
            &construct,
            boost::python::type_id<UnicodeString>());
    }

    static void* convertible(PyObject* obj_ptr)
    {
        if (!(PyString_Check(obj_ptr) || PyUnicode_Check(obj_ptr)))
            return 0;
        return obj_ptr;
    }

    static void construct(
        PyObject* obj_ptr,
        boost::python::converter::rvalue_from_python_stage1_data* data)
    {
        char * value=0;
        if (PyUnicode_Check(obj_ptr)) {
            PyObject *encoded = PyUnicode_AsEncodedString(obj_ptr, "utf8", "replace");
            if (encoded) {
                value = PyString_AsString(encoded);
                Py_DecRef(encoded);
            }
        } else {
            value = PyString_AsString(obj_ptr);
        }
        if (value == 0) boost::python::throw_error_already_set();
        void* storage = (
            (boost::python::converter::rvalue_from_python_storage<UnicodeString>*)
            data)->storage.bytes;
        new (storage) UnicodeString(value);
        data->convertible = storage;
    }
};

void export_feature()
{
    using namespace boost::python;
    using mapnik::Feature;

    implicitly_convertible<int,mapnik::value>();
    implicitly_convertible<double,mapnik::value>();
    implicitly_convertible<UnicodeString,mapnik::value>();
    implicitly_convertible<bool,mapnik::value>();

    std_pair_to_python_converter<std::string const,mapnik::value>();
    to_python_converter<mapnik::value,mapnik_value_to_python>();
    UnicodeString_from_python_str();

    class_<Feature,boost::shared_ptr<Feature>,
	   boost::noncopyable>("Feature",init<int>("Default ctor."))
	.def("id",&Feature::id)
	.def("__str__",&Feature::to_string)
	.def("add_geometry", &feature_add_wkb_geometry)
	.def("num_geometries",&Feature::num_geometries)
	.def("get_geometry", make_function(get_geom1,return_value_policy<reference_existing_object>()))
	.def("envelope", &Feature::envelope)
	.def(map_indexing_suite2<Feature, true >())
	.def("iteritems",iterator<Feature> ())
	// TODO define more mapnik::Feature methods
	;
}
<|endoftext|>


<commit_before>/*****************************************************************************
 *
 * This file is part of Mapnik (c++ mapping toolkit)
 *
 * Copyright (C) 2006 Artem Pavlenko, Jean-Francois Doyon
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 *
 *****************************************************************************/

// boost
#include <boost/python/suite/indexing/indexing_suite.hpp>
//#include <boost/python/suite/indexing/map_indexing_suite.hpp>
#include <boost/python/iterator.hpp>
#include <boost/python/call_method.hpp>
#include <boost/python/tuple.hpp>
#include <boost/python/to_python_converter.hpp>
#include <boost/python.hpp>
#include <boost/noncopyable.hpp>

// mapnik
#include <mapnik/feature.hpp>
#include <mapnik/feature_kv_iterator.hpp>
#include <mapnik/datasource.hpp>
#include <mapnik/wkb.hpp>
#include <mapnik/wkt/wkt_factory.hpp>
#include <mapnik/json/geojson_generator.hpp>

namespace {

using mapnik::Feature;
using mapnik::geometry_utils;
using mapnik::from_wkt;
using mapnik::context_type;
using mapnik::context_ptr;
using mapnik::feature_kv_iterator;

mapnik::geometry_type const& (mapnik::Feature::*get_geometry_by_const_ref)(unsigned) const = &mapnik::Feature::get_geometry;
boost::ptr_vector<mapnik::geometry_type> const& (mapnik::Feature::*get_paths_by_const_ref)() const = &mapnik::Feature::paths;

void feature_add_geometries_from_wkb(Feature &feature, std::string wkb)
{
    geometry_utils::from_wkb(feature.paths(), wkb.c_str(), wkb.size());
}

void feature_add_geometries_from_wkt(Feature &feature, std::string wkt)
{
    bool result = mapnik::from_wkt(wkt, feature.paths());
    if (!result) throw std::runtime_error("Failed to parse WKT");
}

std::string feature_to_geojson(Feature const& feature)
{
    std::string json;
    mapnik::json::feature_generator g;
    if (!g.generate(json,feature))
    {
        throw std::runtime_error("Failed to generate GeoJSON");
    }
    return json;
}

mapnik::value  __getitem__(Feature const& feature, std::string const& name)
{
    return feature.get(name);
}

mapnik::value  __getitem2__(Feature const& feature, std::size_t index)
{
    return feature.get(index);
}

void __setitem__(Feature & feature, std::string const& name, mapnik::value const& val)
{
    feature.put_new(name,val);
}

boost::python::dict attributes(Feature const& f)
{
    boost::python::dict attributes;
    feature_kv_iterator itr = f.begin();
    feature_kv_iterator end = f.end();

    for ( ;itr!=end; ++itr)
    {
        attributes[boost::get<0>(*itr)] = boost::get<1>(*itr);
    }

    return attributes;
}

} // end anonymous namespace

struct UnicodeString_from_python_str
{
    UnicodeString_from_python_str()
    {
        boost::python::converter::registry::push_back(
            &convertible,
            &construct,
            boost::python::type_id<UnicodeString>());
    }

    static void* convertible(PyObject* obj_ptr)
    {
        if (!(
#if PY_VERSION_HEX >= 0x03000000
                PyBytes_Check(obj_ptr)
#else
                PyString_Check(obj_ptr)
#endif
                || PyUnicode_Check(obj_ptr)))
            return 0;
        return obj_ptr;
    }

    static void construct(
        PyObject* obj_ptr,
        boost::python::converter::rvalue_from_python_stage1_data* data)
    {
        char * value=0;
        if (PyUnicode_Check(obj_ptr)) {
            PyObject *encoded = PyUnicode_AsEncodedString(obj_ptr, "utf8", "replace");
            if (encoded) {
#if PY_VERSION_HEX >= 0x03000000
                value = PyBytes_AsString(encoded);
#else
                value = PyString_AsString(encoded);
#endif
                Py_DecRef(encoded);
            }
        } else {
#if PY_VERSION_HEX >= 0x03000000
            value = PyBytes_AsString(obj_ptr);
#else
            value = PyString_AsString(obj_ptr);
#endif
        }
        if (value == 0) boost::python::throw_error_already_set();
        void* storage = (
            (boost::python::converter::rvalue_from_python_storage<UnicodeString>*)
            data)->storage.bytes;
        new (storage) UnicodeString(value);
        data->convertible = storage;
    }
};

struct value_null_from_python
{
    value_null_from_python()
    {
        boost::python::converter::registry::push_back(
            &convertible,
            &construct,
            boost::python::type_id<mapnik::value_null>());
    }

    static void* convertible(PyObject* obj_ptr)
    {
        if (obj_ptr == Py_None) return obj_ptr;
        return 0;
    }

    static void construct(
        PyObject* obj_ptr,
        boost::python::converter::rvalue_from_python_stage1_data* data)
    {
        if (obj_ptr != Py_None) boost::python::throw_error_already_set();
        void* storage = (
            (boost::python::converter::rvalue_from_python_storage<mapnik::value_null>*)
            data)->storage.bytes;
        new (storage) mapnik::value_null();
        data->convertible = storage;
    }
};

void export_feature()
{
    using namespace boost::python;
    using mapnik::Feature;

    // Python to mapnik::value converters
    // NOTE: order matters here. For example value_null must be listed before
    // bool otherwise Py_None will be interpreted as bool (false)
    implicitly_convertible<mapnik::value_unicode_string,mapnik::value>();
    implicitly_convertible<mapnik::value_null,mapnik::value>();
    implicitly_convertible<mapnik::value_integer,mapnik::value>();
    implicitly_convertible<mapnik::value_double,mapnik::value>();
    implicitly_convertible<mapnik::value_bool,mapnik::value>();

    // http://misspent.wordpress.com/2009/09/27/how-to-write-boost-python-converters/
    UnicodeString_from_python_str();
    value_null_from_python();

    class_<context_type,context_ptr,boost::noncopyable>
        ("Context",init<>("Default ctor."))
        .def("push", &context_type::push)
        ;

    class_<Feature,boost::shared_ptr<Feature>,
        boost::noncopyable>("Feature",init<context_ptr,mapnik::value_integer>("Default ctor."))
        .def("id",&Feature::id)
        .def("__str__",&Feature::to_string)
        .def("add_geometries_from_wkb", &feature_add_geometries_from_wkb)
        .def("add_geometries_from_wkt", &feature_add_geometries_from_wkt)
        .def("add_geometry", &Feature::add_geometry)
        .def("num_geometries",&Feature::num_geometries)
        .def("get_geometry", make_function(get_geometry_by_const_ref,return_value_policy<reference_existing_object>()))
        .def("geometries",make_function(get_paths_by_const_ref,return_value_policy<reference_existing_object>()))
        .def("envelope", &Feature::envelope)
        .def("has_key", &Feature::has_key)
        .add_property("attributes",&attributes)
        .def("__setitem__",&__setitem__)
        .def("__contains__",&__getitem__)
        .def("__getitem__",&__getitem__)
        .def("__getitem__",&__getitem2__)
        .def("__len__", &Feature::size)
        .def("context",&Feature::context)
        .def("to_geojson",&feature_to_geojson)
        ;
}
<commit_msg>+ fix method signature<commit_after>/*****************************************************************************
 *
 * This file is part of Mapnik (c++ mapping toolkit)
 *
 * Copyright (C) 2006 Artem Pavlenko, Jean-Francois Doyon
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 *
 *****************************************************************************/

// boost
#include <boost/python/suite/indexing/indexing_suite.hpp>
//#include <boost/python/suite/indexing/map_indexing_suite.hpp>
#include <boost/python/iterator.hpp>
#include <boost/python/call_method.hpp>
#include <boost/python/tuple.hpp>
#include <boost/python/to_python_converter.hpp>
#include <boost/python.hpp>
#include <boost/noncopyable.hpp>

// mapnik
#include <mapnik/feature.hpp>
#include <mapnik/feature_kv_iterator.hpp>
#include <mapnik/datasource.hpp>
#include <mapnik/wkb.hpp>
#include <mapnik/wkt/wkt_factory.hpp>
#include <mapnik/json/geojson_generator.hpp>

namespace {

using mapnik::Feature;
using mapnik::geometry_utils;
using mapnik::from_wkt;
using mapnik::context_type;
using mapnik::context_ptr;
using mapnik::feature_kv_iterator;

mapnik::geometry_type const& (mapnik::Feature::*get_geometry_by_const_ref)(std::size_t) const = &mapnik::Feature::get_geometry;
boost::ptr_vector<mapnik::geometry_type> const& (mapnik::Feature::*get_paths_by_const_ref)() const = &mapnik::Feature::paths;

void feature_add_geometries_from_wkb(Feature &feature, std::string wkb)
{
    geometry_utils::from_wkb(feature.paths(), wkb.c_str(), wkb.size());
}

void feature_add_geometries_from_wkt(Feature &feature, std::string wkt)
{
    bool result = mapnik::from_wkt(wkt, feature.paths());
    if (!result) throw std::runtime_error("Failed to parse WKT");
}

std::string feature_to_geojson(Feature const& feature)
{
    std::string json;
    mapnik::json::feature_generator g;
    if (!g.generate(json,feature))
    {
        throw std::runtime_error("Failed to generate GeoJSON");
    }
    return json;
}

mapnik::value  __getitem__(Feature const& feature, std::string const& name)
{
    return feature.get(name);
}

mapnik::value  __getitem2__(Feature const& feature, std::size_t index)
{
    return feature.get(index);
}

void __setitem__(Feature & feature, std::string const& name, mapnik::value const& val)
{
    feature.put_new(name,val);
}

boost::python::dict attributes(Feature const& f)
{
    boost::python::dict attributes;
    feature_kv_iterator itr = f.begin();
    feature_kv_iterator end = f.end();

    for ( ;itr!=end; ++itr)
    {
        attributes[boost::get<0>(*itr)] = boost::get<1>(*itr);
    }

    return attributes;
}

} // end anonymous namespace

struct UnicodeString_from_python_str
{
    UnicodeString_from_python_str()
    {
        boost::python::converter::registry::push_back(
            &convertible,
            &construct,
            boost::python::type_id<UnicodeString>());
    }

    static void* convertible(PyObject* obj_ptr)
    {
        if (!(
#if PY_VERSION_HEX >= 0x03000000
                PyBytes_Check(obj_ptr)
#else
                PyString_Check(obj_ptr)
#endif
                || PyUnicode_Check(obj_ptr)))
            return 0;
        return obj_ptr;
    }

    static void construct(
        PyObject* obj_ptr,
        boost::python::converter::rvalue_from_python_stage1_data* data)
    {
        char * value=0;
        if (PyUnicode_Check(obj_ptr)) {
            PyObject *encoded = PyUnicode_AsEncodedString(obj_ptr, "utf8", "replace");
            if (encoded) {
#if PY_VERSION_HEX >= 0x03000000
                value = PyBytes_AsString(encoded);
#else
                value = PyString_AsString(encoded);
#endif
                Py_DecRef(encoded);
            }
        } else {
#if PY_VERSION_HEX >= 0x03000000
            value = PyBytes_AsString(obj_ptr);
#else
            value = PyString_AsString(obj_ptr);
#endif
        }
        if (value == 0) boost::python::throw_error_already_set();
        void* storage = (
            (boost::python::converter::rvalue_from_python_storage<UnicodeString>*)
            data)->storage.bytes;
        new (storage) UnicodeString(value);
        data->convertible = storage;
    }
};

struct value_null_from_python
{
    value_null_from_python()
    {
        boost::python::converter::registry::push_back(
            &convertible,
            &construct,
            boost::python::type_id<mapnik::value_null>());
    }

    static void* convertible(PyObject* obj_ptr)
    {
        if (obj_ptr == Py_None) return obj_ptr;
        return 0;
    }

    static void construct(
        PyObject* obj_ptr,
        boost::python::converter::rvalue_from_python_stage1_data* data)
    {
        if (obj_ptr != Py_None) boost::python::throw_error_already_set();
        void* storage = (
            (boost::python::converter::rvalue_from_python_storage<mapnik::value_null>*)
            data)->storage.bytes;
        new (storage) mapnik::value_null();
        data->convertible = storage;
    }
};

void export_feature()
{
    using namespace boost::python;
    using mapnik::Feature;

    // Python to mapnik::value converters
    // NOTE: order matters here. For example value_null must be listed before
    // bool otherwise Py_None will be interpreted as bool (false)
    implicitly_convertible<mapnik::value_unicode_string,mapnik::value>();
    implicitly_convertible<mapnik::value_null,mapnik::value>();
    implicitly_convertible<mapnik::value_integer,mapnik::value>();
    implicitly_convertible<mapnik::value_double,mapnik::value>();
    implicitly_convertible<mapnik::value_bool,mapnik::value>();

    // http://misspent.wordpress.com/2009/09/27/how-to-write-boost-python-converters/
    UnicodeString_from_python_str();
    value_null_from_python();

    class_<context_type,context_ptr,boost::noncopyable>
        ("Context",init<>("Default ctor."))
        .def("push", &context_type::push)
        ;

    class_<Feature,boost::shared_ptr<Feature>,
        boost::noncopyable>("Feature",init<context_ptr,mapnik::value_integer>("Default ctor."))
        .def("id",&Feature::id)
        .def("__str__",&Feature::to_string)
        .def("add_geometries_from_wkb", &feature_add_geometries_from_wkb)
        .def("add_geometries_from_wkt", &feature_add_geometries_from_wkt)
        .def("add_geometry", &Feature::add_geometry)
        .def("num_geometries",&Feature::num_geometries)
        .def("get_geometry", make_function(get_geometry_by_const_ref,return_value_policy<reference_existing_object>()))
        .def("geometries",make_function(get_paths_by_const_ref,return_value_policy<reference_existing_object>()))
        .def("envelope", &Feature::envelope)
        .def("has_key", &Feature::has_key)
        .add_property("attributes",&attributes)
        .def("__setitem__",&__setitem__)
        .def("__contains__",&__getitem__)
        .def("__getitem__",&__getitem__)
        .def("__getitem__",&__getitem2__)
        .def("__len__", &Feature::size)
        .def("context",&Feature::context)
        .def("to_geojson",&feature_to_geojson)
        ;
}
<|endoftext|>


<commit_before>/*
   This file is part of the clazy static checker.

  Copyright (C) 2016 Sergio Martins <smartins@kde.org>

  This library is free software; you can redistribute it and/or
  modify it under the terms of the GNU Library General Public
  License as published by the Free Software Foundation; either
  version 2 of the License, or (at your option) any later version.

  This library is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  Library General Public License for more details.

  You should have received a copy of the GNU Library General Public License
  along with this library; see the file COPYING.LIB.  If not, write to
  the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
  Boston, MA 02110-1301, USA.
*/

#include "function-args-by-value.h"
#include "Utils.h"
#include "checkmanager.h"
#include "StringUtils.h"
#include "TypeUtils.h"
#include "FixItUtils.h"

#include <clang/AST/AST.h>
#include <clang/Lex/Lexer.h>

using namespace clang;
using namespace std;

enum Fixit {
    FixitNone = 0,
    FixitAll = 0x1 // More granularity isn't needed I guess
};

// TODO, go over all these
static bool shouldIgnoreClass(CXXRecordDecl *record)
{
    if (!record)
        return false;

    if (Utils::isSharedPointer(record))
        return true;

    static const vector<string> ignoreList = {"QDebug", // Too many warnings
                                              "QGenericReturnArgument",
                                              "QColor", // TODO: Remove in Qt6
                                              "QStringRef", // TODO: Remove in Qt6
                                              "QList::const_iterator", // TODO: Remove in Qt6
                                              "QJsonArray::const_iterator", // TODO: Remove in Qt6
                                              "QList<QString>::const_iterator",  // TODO: Remove in Qt6
                                              "QtMetaTypePrivate::QSequentialIterableImpl",
                                              "QtMetaTypePrivate::QAssociativeIterableImpl",
                                              "QVariantComparisonHelper",
                                              "QHashDummyValue", "QCharRef", "QString::Null"
                                             };
    return clazy_std::contains(ignoreList, record->getQualifiedNameAsString());
}

static bool shouldIgnoreFunction(clang::FunctionDecl *function)
{
    // Too many warnings in operator<<
    static const vector<string> ignoreList = {"operator<<"};
    static const vector<string> qualifiedIgnoreList = {"QDBusMessage::createErrorReply", // Fixed in Qt6
                                                       "QMenu::exec", // Fixed in Qt6
                                                       "QTextFrame::iterator", // Fixed in Qt6
                                                       "QGraphicsWidget::addActions", // Fixed in Qt6
                                                       "QListWidget::mimeData", // Fixed in Qt6
                                                       "QTableWidget::mimeData", // Fixed in Qt6
                                                       "QTreeWidget::mimeData", // Fixed in Qt6
                                                       "QWidget::addActions", // Fixed in Qt6
                                                       "QSslCertificate::verify", // Fixed in Qt6
                                                       "QSslConfiguration::setAllowedNextProtocols" // Fixed in Qt6
                                                      };
    if (clazy_std::contains(ignoreList, function->getNameAsString()))
        return true;

    return clazy_std::contains(qualifiedIgnoreList, function->getQualifiedNameAsString());
}

FunctionArgsByValue::FunctionArgsByValue(const std::string &name, ClazyContext *context)
    : CheckBase(name, context)
{
}

void FunctionArgsByValue::VisitDecl(Decl *decl)
{
    processFunction(dyn_cast<FunctionDecl>(decl));
}

void FunctionArgsByValue::VisitStmt(Stmt *stmt)
{
    if (LambdaExpr *lambda = dyn_cast<LambdaExpr>(stmt))
        processFunction(lambda->getCallOperator());
}

void FunctionArgsByValue::processFunction(FunctionDecl *func)
{
    if (!func || shouldIgnoreFunction(func) ||
        !func->isThisDeclarationADefinition() || func->isDeleted())
        return;

    Stmt *body = func->getBody();

    int i = -1;
    for (auto param : Utils::functionParameters(func)) {
        i++;
        QualType paramQt = TypeUtils::unrefQualType(param->getType());
        const Type *paramType = paramQt.getTypePtrOrNull();
        if (!paramType || paramType->isIncompleteType() || paramType->isDependentType())
            continue;

        if (shouldIgnoreClass(paramType->getAsCXXRecordDecl()))
            continue;

        TypeUtils::QualTypeClassification classif;
        bool success = TypeUtils::classifyQualType(&m_astContext, param, classif, body);
        if (!success)
            continue;

        if (classif.passSmallTrivialByValue) {
            std::vector<FixItHint> fixits;
            if (isFixitEnabled(FixitAll)) {
                for (auto redecl : func->redecls()) { // Fix in both header and .cpp
                    FunctionDecl *fdecl = dyn_cast<FunctionDecl>(redecl);
                    const ParmVarDecl *param = fdecl->getParamDecl(i);
                    fixits.push_back(fixit(fdecl, param, classif));
                }
            }

            const string paramStr = param->getType().getAsString();
            string error = "Pass small and trivially-copyable type by value (" + paramStr + ')';
            emitWarning(param->getLocStart(), error.c_str(), fixits);
        }
    }
}

FixItHint FunctionArgsByValue::fixit(FunctionDecl *func, const ParmVarDecl *param,
                                     TypeUtils::QualTypeClassification)
{
    QualType qt = TypeUtils::unrefQualType(param->getType());
    qt.removeLocalConst();
    const string typeName = qt.getAsString(PrintingPolicy(lo()));
    string replacement = typeName + ' ' + string(param->getName());
    SourceLocation startLoc = param->getLocStart();
    SourceLocation endLoc = param->getLocEnd();

    const int numRedeclarations = std::distance(func->redecls_begin(), func->redecls_end());
    const bool definitionIsAlsoDeclaration = numRedeclarations == 1;
    const bool isDeclarationButNotDefinition = !func->doesThisDeclarationHaveABody();

    if (param->hasDefaultArg() && (isDeclarationButNotDefinition || definitionIsAlsoDeclaration)) {
        endLoc = param->getDefaultArg()->getLocStart().getLocWithOffset(-1);
        replacement += " =";
    }

    if (!startLoc.isValid() || !endLoc.isValid()) {
        llvm::errs() << "Internal error could not apply fixit " << startLoc.printToString(sm())
                     << ';' << endLoc.printToString(sm()) << "\n";
        return {};
    }

    return FixItUtils::createReplacement({ startLoc, endLoc }, replacement);
}

REGISTER_CHECK("function-args-by-value", FunctionArgsByValue, CheckLevel2)
<commit_msg>function-args-by-value: Minor optimization<commit_after>/*
   This file is part of the clazy static checker.

  Copyright (C) 2016 Sergio Martins <smartins@kde.org>

  This library is free software; you can redistribute it and/or
  modify it under the terms of the GNU Library General Public
  License as published by the Free Software Foundation; either
  version 2 of the License, or (at your option) any later version.

  This library is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  Library General Public License for more details.

  You should have received a copy of the GNU Library General Public License
  along with this library; see the file COPYING.LIB.  If not, write to
  the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
  Boston, MA 02110-1301, USA.
*/

#include "function-args-by-value.h"
#include "Utils.h"
#include "checkmanager.h"
#include "StringUtils.h"
#include "TypeUtils.h"
#include "FixItUtils.h"

#include <clang/AST/AST.h>
#include <clang/Lex/Lexer.h>

using namespace clang;
using namespace std;

enum Fixit {
    FixitNone = 0,
    FixitAll = 0x1 // More granularity isn't needed I guess
};

// TODO, go over all these
static bool shouldIgnoreClass(CXXRecordDecl *record)
{
    if (!record)
        return false;

    if (Utils::isSharedPointer(record))
        return true;

    static const vector<string> ignoreList = {"QDebug", // Too many warnings
                                              "QGenericReturnArgument",
                                              "QColor", // TODO: Remove in Qt6
                                              "QStringRef", // TODO: Remove in Qt6
                                              "QList::const_iterator", // TODO: Remove in Qt6
                                              "QJsonArray::const_iterator", // TODO: Remove in Qt6
                                              "QList<QString>::const_iterator",  // TODO: Remove in Qt6
                                              "QtMetaTypePrivate::QSequentialIterableImpl",
                                              "QtMetaTypePrivate::QAssociativeIterableImpl",
                                              "QVariantComparisonHelper",
                                              "QHashDummyValue", "QCharRef", "QString::Null"
                                             };
    return clazy_std::contains(ignoreList, record->getQualifiedNameAsString());
}

static bool shouldIgnoreFunction(clang::FunctionDecl *function)
{
    // Too many warnings in operator<<
    static const vector<string> ignoreList = {"operator<<"};
    static const vector<string> qualifiedIgnoreList = {"QDBusMessage::createErrorReply", // Fixed in Qt6
                                                       "QMenu::exec", // Fixed in Qt6
                                                       "QTextFrame::iterator", // Fixed in Qt6
                                                       "QGraphicsWidget::addActions", // Fixed in Qt6
                                                       "QListWidget::mimeData", // Fixed in Qt6
                                                       "QTableWidget::mimeData", // Fixed in Qt6
                                                       "QTreeWidget::mimeData", // Fixed in Qt6
                                                       "QWidget::addActions", // Fixed in Qt6
                                                       "QSslCertificate::verify", // Fixed in Qt6
                                                       "QSslConfiguration::setAllowedNextProtocols" // Fixed in Qt6
                                                      };
    if (clazy_std::contains(ignoreList, function->getNameAsString()))
        return true;

    return clazy_std::contains(qualifiedIgnoreList, function->getQualifiedNameAsString());
}

FunctionArgsByValue::FunctionArgsByValue(const std::string &name, ClazyContext *context)
    : CheckBase(name, context)
{
}

void FunctionArgsByValue::VisitDecl(Decl *decl)
{
    processFunction(dyn_cast<FunctionDecl>(decl));
}

void FunctionArgsByValue::VisitStmt(Stmt *stmt)
{
    if (LambdaExpr *lambda = dyn_cast<LambdaExpr>(stmt))
        processFunction(lambda->getCallOperator());
}

void FunctionArgsByValue::processFunction(FunctionDecl *func)
{
    if (!func || !func->isThisDeclarationADefinition() ||
        func->isDeleted() || shouldIgnoreFunction(func))
        return;

    Stmt *body = func->getBody();

    int i = -1;
    for (auto param : Utils::functionParameters(func)) {
        i++;
        QualType paramQt = TypeUtils::unrefQualType(param->getType());
        const Type *paramType = paramQt.getTypePtrOrNull();
        if (!paramType || paramType->isIncompleteType() || paramType->isDependentType())
            continue;

        if (shouldIgnoreClass(paramType->getAsCXXRecordDecl()))
            continue;

        TypeUtils::QualTypeClassification classif;
        bool success = TypeUtils::classifyQualType(&m_astContext, param, classif, body);
        if (!success)
            continue;

        if (classif.passSmallTrivialByValue) {
            std::vector<FixItHint> fixits;
            if (isFixitEnabled(FixitAll)) {
                for (auto redecl : func->redecls()) { // Fix in both header and .cpp
                    FunctionDecl *fdecl = dyn_cast<FunctionDecl>(redecl);
                    const ParmVarDecl *param = fdecl->getParamDecl(i);
                    fixits.push_back(fixit(fdecl, param, classif));
                }
            }

            const string paramStr = param->getType().getAsString();
            string error = "Pass small and trivially-copyable type by value (" + paramStr + ')';
            emitWarning(param->getLocStart(), error.c_str(), fixits);
        }
    }
}

FixItHint FunctionArgsByValue::fixit(FunctionDecl *func, const ParmVarDecl *param,
                                     TypeUtils::QualTypeClassification)
{
    QualType qt = TypeUtils::unrefQualType(param->getType());
    qt.removeLocalConst();
    const string typeName = qt.getAsString(PrintingPolicy(lo()));
    string replacement = typeName + ' ' + string(param->getName());
    SourceLocation startLoc = param->getLocStart();
    SourceLocation endLoc = param->getLocEnd();

    const int numRedeclarations = std::distance(func->redecls_begin(), func->redecls_end());
    const bool definitionIsAlsoDeclaration = numRedeclarations == 1;
    const bool isDeclarationButNotDefinition = !func->doesThisDeclarationHaveABody();

    if (param->hasDefaultArg() && (isDeclarationButNotDefinition || definitionIsAlsoDeclaration)) {
        endLoc = param->getDefaultArg()->getLocStart().getLocWithOffset(-1);
        replacement += " =";
    }

    if (!startLoc.isValid() || !endLoc.isValid()) {
        llvm::errs() << "Internal error could not apply fixit " << startLoc.printToString(sm())
                     << ';' << endLoc.printToString(sm()) << "\n";
        return {};
    }

    return FixItUtils::createReplacement({ startLoc, endLoc }, replacement);
}

REGISTER_CHECK("function-args-by-value", FunctionArgsByValue, CheckLevel2)
<|endoftext|>


<commit_before>#include "stdafx.h"

#include "d3d.h"
#include <SADXModLoader.h>
#include <Trampoline.h>

#include "lantern.h"
#include "../include/lanternapi.h"
#include "globals.h"

VoidFunc(sub_541990, 0x541990);
VoidFunc(sub_543F20, 0x543F20);

static const auto sub_541FC0 = (void*)0x00541FC0;

static Trampoline* Obj_Past_t = nullptr;

static void __cdecl Obj_Past_Delete_r(ObjectMaster* _this)
{
	d3d::SetShaderFlags(ShaderFlags_Blend, false);
	set_diffuse_blend(-1, -1);
	set_specular_blend(-1, -1);
	Obj_Past_Delete(_this);
}

static void __cdecl Obj_Past_r(ObjectMaster *_this)
{
	auto entity = _this->Data1;
	switch (entity->Action)
	{
		case 0:
			d3d::SetShaderFlags(ShaderFlags_Blend, true);

			entity->InvulnerableTime = CurrentAct;
			sub_543F20();
			memset((void*)0x3C63690, 0, sizeof(ObjectMaster*) * 4);
			_this->DeleteSub = Obj_Past_Delete_r;
			entity->Action = 1;
			break;

		case 1:
			// teeny tiny usercall function. I ain't writin' no wrapper for that.
			__asm
			{
				mov eax, [_this]
				call sub_541FC0
			}
			entity->Action = 2;
			break;

		case 2:
			if (CurrentAct == entity->InvulnerableTime)
			{
				if (!entity->InvulnerableTime)
				{
					QueueSound_DualEntity(1108, entity, 1, nullptr, 2);
				}
				else if (CurrentAct == 2 && d3d::effect)
				{
					entity->Rotation.x += NJM_DEG_ANG(4.561875f);
					entity->Rotation.x %= 65536;
					auto f = (njSin(entity->Rotation.x) + 1.0f) / 2.0f;
					set_diffuse_blend(0, 5);
					set_specular_blend(0, 5);
					set_specular_blend(1, 5);
					set_blend_factor(f);
				}
			}
			else
			{
				entity->Action = 3;
			}
			break;

		case 3:
			sub_541990();
			entity->Action = 1;
			break;

		default:
			break;
	}
}

void Past_Init()
{
	Obj_Past_t = new Trampoline(0x005420C0, 0x005420C5, Obj_Past_r);
}
<commit_msg>use api entirely for obj_past<commit_after>#include "stdafx.h"

#include "d3d.h"
#include <SADXModLoader.h>
#include <Trampoline.h>

#include "../include/lanternapi.h"
#include "globals.h"

VoidFunc(sub_541990, 0x541990);
VoidFunc(sub_543F20, 0x543F20);

static const auto sub_541FC0 = (void*)0x00541FC0;

static Trampoline* Obj_Past_t = nullptr;

static void __cdecl Obj_Past_Delete_r(ObjectMaster* _this)
{
	// Disable blending in the shader so it doesn't do extra work.
	set_shader_flags(ShaderFlags_Blend, false);

	// Reset blend indices.
	set_blend(-1, -1);

	Obj_Past_Delete(_this);
}

static void __cdecl Obj_Past_r(ObjectMaster *_this)
{
	auto entity = _this->Data1;
	switch (entity->Action)
	{
		case 0:
			// Enables palette blending in the shader.
			set_shader_flags(ShaderFlags_Blend, true);

			entity->InvulnerableTime = CurrentAct;
			sub_543F20();
			memset((void*)0x3C63690, 0, sizeof(ObjectMaster*) * 4);
			_this->DeleteSub = Obj_Past_Delete_r;
			entity->Action = 1;
			break;

		case 1:
			// teeny tiny usercall function. I ain't writin' no wrapper for that.
			__asm
			{
				mov eax, [_this]
				call sub_541FC0
			}
			entity->Action = 2;
			break;

		case 2:
			if (CurrentAct == entity->InvulnerableTime)
			{
				if (!entity->InvulnerableTime)
				{
					QueueSound_DualEntity(1108, entity, 1, nullptr, 2);
				}
				else if (CurrentAct == 2 && d3d::effect)
				{
					entity->Rotation.x += NJM_DEG_ANG(4.561875f);
					entity->Rotation.x %= 65536;
					auto f = (njSin(entity->Rotation.x) + 1.0f) / 2.0f;

					// Blend both diffuse and specular index 0 to index 5.
					set_blend(0, 5);
					// Set the blend factor, where 0 is the source index and 1 is the target.
					set_blend_factor(f);
				}
			}
			else
			{
				entity->Action = 3;
			}
			break;

		case 3:
			sub_541990();
			entity->Action = 1;
			break;

		default:
			break;
	}
}

void Past_Init()
{
	Obj_Past_t = new Trampoline(0x005420C0, 0x005420C5, Obj_Past_r);
}
<|endoftext|>


<commit_before>/***************************************
** Tsunagari Tile Engine              **
** tile-grid.cpp                      **
** Copyright 2011-2015 Michael Reiley **
** Copyright 2011-2019 Paul Merrill   **
***************************************/

// **********
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to
// deal in the Software without restriction, including without limitation the
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
// IN THE SOFTWARE.
// **********

#include "core/tile-grid.h"

#include "core/log.h"
#include "util/assert.h"
#include "util/math2.h"
#include "util/string.h"

TileType*
TileGrid::getTileType(icoord phys) noexcept {
    int x = dim.x;
    int y = dim.y;

    if (loopX) {
        phys.x = wrap(0, phys.x, dim.x);
    }

    if (loopY) {
        phys.y = wrap(0, phys.y, dim.y);
    }

    int idx = (phys.z * y + phys.y) * x + phys.x;
    return types[idx];
}

Tile*
TileGrid::getTile(icoord phys) noexcept {
    int x = dim.x;
    int y = dim.y;

    if (loopX) {
        phys.x = wrap(0, phys.x, dim.x);
    }

    if (loopY) {
        phys.y = wrap(0, phys.y, dim.y);
    }

    int idx = (phys.z * y + phys.y) * x + phys.x;
    return &grid[idx];
}

Tile*
TileGrid::getTile(vicoord virt) noexcept {
    return getTile(virt2phys(virt));
}

Tile*
TileGrid::getTile(rcoord virt) noexcept {
    return getTile(virt2phys(virt));
}

const Tile*
TileGrid::getTile(icoord phys) const noexcept {
    int x = dim.x;
    int y = dim.y;

    if (loopX) {
        phys.x = wrap(0, phys.x, dim.x);
    }

    if (loopY) {
        phys.y = wrap(0, phys.y, dim.y);
    }

    assert_(inBounds(phys));

    int idx = (phys.z * y + phys.y) * x + phys.x;
    return &grid[idx];
}

const Tile*
TileGrid::getTile(vicoord virt) const noexcept {
    return getTile(virt2phys(virt));
}

const Tile*
TileGrid::getTile(rcoord virt) const noexcept {
    return getTile(virt2phys(virt));
}

ivec3
TileGrid::getDimensions() const noexcept {
    return dim;
}

ivec2
TileGrid::getTileDimensions() const noexcept {
    return tileDim;
}

bool
TileGrid::doesLoopInX() const noexcept {
    return loopX;
}

bool
TileGrid::doesLoopInY() const noexcept {
    return loopY;
}

bool
TileGrid::inBounds(icoord phys) const noexcept {
    return (loopX || (0 <= phys.x && phys.x < dim.x)) &&
           (loopY || (0 <= phys.y && phys.y < dim.y)) &&
           (0 <= phys.z && phys.z < dim.z);
}

bool
TileGrid::inBounds(vicoord virt) const noexcept {
    return inBounds(virt2phys(virt));
}

bool
TileGrid::inBounds(rcoord virt) const noexcept {
    return inBounds(virt2phys(virt));
}

vicoord
TileGrid::phys2virt_vi(icoord phys) const noexcept {
    return vicoord{phys.x, phys.y, indexDepth(phys.z)};
}

rcoord
TileGrid::phys2virt_r(icoord phys) const noexcept {
    return rcoord{static_cast<double>(phys.x * tileDim.x),
                  static_cast<double>(phys.y * tileDim.y),
                  indexDepth(phys.z)};
}

icoord
TileGrid::virt2phys(vicoord virt) const noexcept {
    return icoord{static_cast<int>(virt.x),
                  static_cast<int>(virt.y),
                  depthIndex(virt.z)};
}

icoord
TileGrid::virt2phys(rcoord virt) const noexcept {
    return icoord{static_cast<int>(virt.x) / tileDim.x,
                  static_cast<int>(virt.y) / tileDim.y,
                  depthIndex(virt.z)};
}

rcoord
TileGrid::virt2virt(vicoord virt) const noexcept {
    return rcoord{static_cast<double>(virt.x * tileDim.x),
                  static_cast<double>(virt.y * tileDim.y),
                  virt.z};
}

vicoord
TileGrid::virt2virt(rcoord virt) const noexcept {
    return vicoord{static_cast<int>(virt.x) / tileDim.x,
                   static_cast<int>(virt.y) / tileDim.y,
                   virt.z};
}

int
TileGrid::depthIndex(double depth) const noexcept {
    auto it = depth2idx.find(depth);
    if (it == depth2idx.end()) {
        Log::fatal("TileGrid",
                   String() << "Attempt to access invalid layer: " << depth);
    }
    return it.value();
}

double
TileGrid::indexDepth(int idx) const noexcept {
    assert_(0 <= idx && idx <= dim.z);
    return idx2depth[(size_t)idx];
}
<commit_msg>core/tile-grid: Fix getTileType() style<commit_after>/***************************************
** Tsunagari Tile Engine              **
** tile-grid.cpp                      **
** Copyright 2011-2015 Michael Reiley **
** Copyright 2011-2019 Paul Merrill   **
***************************************/

// **********
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to
// deal in the Software without restriction, including without limitation the
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
// IN THE SOFTWARE.
// **********

#include "core/tile-grid.h"

#include "core/log.h"
#include "util/assert.h"
#include "util/math2.h"
#include "util/string.h"

TileType*
TileGrid::getTileType(icoord phys) noexcept {
    int x = dim.x;
    int y = dim.y;

    if (loopX) {
        phys.x = wrap(0, phys.x, x);
    }

    if (loopY) {
        phys.y = wrap(0, phys.y, y);
    }

    int idx = (phys.z * y + phys.y) * x + phys.x;
    return types[idx];
}

Tile*
TileGrid::getTile(icoord phys) noexcept {
    int x = dim.x;
    int y = dim.y;

    if (loopX) {
        phys.x = wrap(0, phys.x, dim.x);
    }

    if (loopY) {
        phys.y = wrap(0, phys.y, dim.y);
    }

    int idx = (phys.z * y + phys.y) * x + phys.x;
    return &grid[idx];
}

Tile*
TileGrid::getTile(vicoord virt) noexcept {
    return getTile(virt2phys(virt));
}

Tile*
TileGrid::getTile(rcoord virt) noexcept {
    return getTile(virt2phys(virt));
}

const Tile*
TileGrid::getTile(icoord phys) const noexcept {
    int x = dim.x;
    int y = dim.y;

    if (loopX) {
        phys.x = wrap(0, phys.x, dim.x);
    }

    if (loopY) {
        phys.y = wrap(0, phys.y, dim.y);
    }

    assert_(inBounds(phys));

    int idx = (phys.z * y + phys.y) * x + phys.x;
    return &grid[idx];
}

const Tile*
TileGrid::getTile(vicoord virt) const noexcept {
    return getTile(virt2phys(virt));
}

const Tile*
TileGrid::getTile(rcoord virt) const noexcept {
    return getTile(virt2phys(virt));
}

ivec3
TileGrid::getDimensions() const noexcept {
    return dim;
}

ivec2
TileGrid::getTileDimensions() const noexcept {
    return tileDim;
}

bool
TileGrid::doesLoopInX() const noexcept {
    return loopX;
}

bool
TileGrid::doesLoopInY() const noexcept {
    return loopY;
}

bool
TileGrid::inBounds(icoord phys) const noexcept {
    return (loopX || (0 <= phys.x && phys.x < dim.x)) &&
           (loopY || (0 <= phys.y && phys.y < dim.y)) &&
           (0 <= phys.z && phys.z < dim.z);
}

bool
TileGrid::inBounds(vicoord virt) const noexcept {
    return inBounds(virt2phys(virt));
}

bool
TileGrid::inBounds(rcoord virt) const noexcept {
    return inBounds(virt2phys(virt));
}

vicoord
TileGrid::phys2virt_vi(icoord phys) const noexcept {
    return vicoord{phys.x, phys.y, indexDepth(phys.z)};
}

rcoord
TileGrid::phys2virt_r(icoord phys) const noexcept {
    return rcoord{static_cast<double>(phys.x * tileDim.x),
                  static_cast<double>(phys.y * tileDim.y),
                  indexDepth(phys.z)};
}

icoord
TileGrid::virt2phys(vicoord virt) const noexcept {
    return icoord{static_cast<int>(virt.x),
                  static_cast<int>(virt.y),
                  depthIndex(virt.z)};
}

icoord
TileGrid::virt2phys(rcoord virt) const noexcept {
    return icoord{static_cast<int>(virt.x) / tileDim.x,
                  static_cast<int>(virt.y) / tileDim.y,
                  depthIndex(virt.z)};
}

rcoord
TileGrid::virt2virt(vicoord virt) const noexcept {
    return rcoord{static_cast<double>(virt.x * tileDim.x),
                  static_cast<double>(virt.y * tileDim.y),
                  virt.z};
}

vicoord
TileGrid::virt2virt(rcoord virt) const noexcept {
    return vicoord{static_cast<int>(virt.x) / tileDim.x,
                   static_cast<int>(virt.y) / tileDim.y,
                   virt.z};
}

int
TileGrid::depthIndex(double depth) const noexcept {
    auto it = depth2idx.find(depth);
    if (it == depth2idx.end()) {
        Log::fatal("TileGrid",
                   String() << "Attempt to access invalid layer: " << depth);
    }
    return it.value();
}

double
TileGrid::indexDepth(int idx) const noexcept {
    assert_(0 <= idx && idx <= dim.z);
    return idx2depth[(size_t)idx];
}
<|endoftext|>