<commit_before>// This file is distributed under the MIT license.
// See the LICENSE file for details.

#include <array>
#include <cstddef>

#include <visionaray/material.h>

namespace visionaray
{

//-------------------------------------------------------------------------------------------------
// Public interface
//

template <typename T, typename ...Ts>
template <template <typename> class M>
inline generic_material<T, Ts...>::generic_material(M<typename T::scalar_type> const& material)
    : generic_material<T, Ts...>::base_type(material)
{
}

template <typename T, typename ...Ts>
VSNRAY_FUNC
inline bool generic_material<T, Ts...>::is_emissive() const
{
    return apply_visitor( is_emissive_visitor(), *this );
}

template <typename T, typename ...Ts>
VSNRAY_FUNC
inline spectrum<typename T::scalar_type> generic_material<T, Ts...>::ambient() const
{
    return apply_visitor( ambient_visitor(), *this );
}

template <typename T, typename ...Ts>
template <typename SR>
VSNRAY_FUNC
inline spectrum<typename SR::scalar_type> generic_material<T, Ts...>::shade(SR const& sr) const
{
    return apply_visitor( shade_visitor<SR>(sr), *this );
}

template <typename T, typename ...Ts>
template <typename SR, typename U, typename Sampler>
VSNRAY_FUNC
inline spectrum<U> generic_material<T, Ts...>::sample(
        SR const&       sr,
        vector<3, U>&   refl_dir,
        U&              pdf,
        Sampler&        sampler
        ) const
{
    return apply_visitor( sample_visitor<SR, U, Sampler>(sr, refl_dir, pdf, sampler), *this );
}

//-------------------------------------------------------------------------------------------------
// Private variant visitors
//

template <typename T, typename ...Ts>
struct generic_material<T, Ts...>::is_emissive_visitor
{
    using Base = generic_material<T, Ts...>;
    using return_type = bool;

    template <typename X>
    VSNRAY_FUNC
    bool operator()(X) const
    {
        return false;
    }

    VSNRAY_FUNC
    bool operator()(emissive<typename Base::scalar_type>) const
    {
        return true;
    }
};

template <typename T, typename ...Ts>
struct generic_material<T, Ts...>::ambient_visitor
{
    using Base = generic_material<T, Ts...>;
    using return_type = spectrum<typename Base::scalar_type>;

    template <typename X>
    VSNRAY_FUNC
    return_type operator()(X const& ref) const
    {
        return ref.ambient();
    }
};

template <typename T, typename ...Ts>
template <typename SR>
struct generic_material<T, Ts...>::shade_visitor
{
    using return_type = spectrum<typename SR::scalar_type>;

    VSNRAY_FUNC
    shade_visitor(SR const& sr) : sr_(sr) {}

    template <typename X>
    VSNRAY_FUNC
    return_type operator()(X const& ref) const
    {
        return ref.shade(sr_);
    }

    SR const& sr_;
};

template <typename T, typename ...Ts>
template <typename SR, typename U, typename Sampler>
struct generic_material<T, Ts...>::sample_visitor
{
    using return_type = spectrum<typename SR::scalar_type>;

    VSNRAY_FUNC
    sample_visitor(SR const& sr, vector<3, U>& refl_dir, U& pdf, Sampler& sampler)
        : sr_(sr)
        , refl_dir_(refl_dir)
        , pdf_(pdf)
        , sampler_(sampler)
    {
    }

    template <typename X>
    VSNRAY_FUNC
    return_type operator()(X const& ref) const
    {
        return ref.sample(sr_, refl_dir_, pdf_, sampler_);
    }

    SR const&       sr_;
    vector<3, U>&   refl_dir_;
    U&              pdf_;
    Sampler&        sampler_;
};

namespace simd
{

template <size_t N, typename ...Ts>
class generic_material;

//-------------------------------------------------------------------------------------------------
// SSE type used internally. Contains four generic materials
//

template <typename ...Ts>
class generic_material<4, Ts...>
{
public:

    using scalar_type      = simd::float4;
    using single_material  = visionaray::generic_material<Ts...>;

public:

    generic_material(std::array<single_material, 4> const& mats)
        : mats_(mats)
    {
    }

    single_material& get(int i)
    {
        return mats_[i];
    }

    single_material const& get(int i) const
    {
        return mats_[i];
    }

    simd::mask4 is_emissive() const
    {
        return simd::mask4(
                mats_[0].is_emissive(),
                mats_[1].is_emissive(),
                mats_[2].is_emissive(),
                mats_[3].is_emissive()
                );
    }

    spectrum<simd::float4> ambient() const
    {
        std::array<spectrum<float>, 4> amb;

        for (size_t i = 0; i < 4; ++i)
        {
            amb[i] = mats_[i].ambient();
        }

        return simd::pack(amb);
    }

    template <typename SR>
    spectrum<simd::float4> shade(SR const& sr) const
    {
        auto sr4 = unpack(sr);

        std::array<spectrum<float>, 4> shaded;

        for (size_t i = 0; i < 4; ++i)
        {
            shaded[i] = mats_[i].shade(sr4[i]);
        }

        return simd::pack(shaded);
    }

    template <typename SR, typename S /* sampler */>
    spectrum<simd::float4> sample(
            SR const&                   sr,
            vector<3, simd::float4>&    refl_dir,
            simd::float4&               pdf,
            S&                          samp
            ) const
    {
        using float_array = typename simd::aligned_array<simd::float4>::type;

        auto sr4 = unpack(sr);
        auto& s = samp.get_sampler();

        std::array<vector<3, float>, 4> rd4;
        float_array                     pdf4;
        std::array<spectrum<float>, 4>  sampled;

        for (size_t i = 0; i < 4; ++i)
        {
            sampled[i] = mats_[i].sample(sr4[i], rd4[i], pdf4[i], s);
        }

        refl_dir = simd::pack(rd4);
        pdf = simd::float4(pdf4);
        return simd::pack(sampled);
    }

private:

    std::array<single_material, 4> mats_;

};

#if VSNRAY_SIMD_ISA >= VSNRAY_SIMD_ISA_AVX

//-------------------------------------------------------------------------------------------------
// AVX type used internally. Contains eight generic materials
//

template <typename ...Ts>
class generic_material<8, Ts...>
{
public:

    using scalar_type     = simd::float8;
    using single_material = visionaray::generic_material<Ts...>;

public:

    generic_material(std::array<single_material, 8> const& mats)
        : mats_(mats)
    {
    }

    single_material& get(int i)
    {
        return mats_[i];
    }

    single_material const& get(int i) const
    {
        return mats_[i];
    }

    simd::mask8 is_emissive() const
    {
        return simd::mask8(
                mats_[0].is_emissive(),
                mats_[1].is_emissive(),
                mats_[2].is_emissive(),
                mats_[3].is_emissive(),
                mats_[4].is_emissive(),
                mats_[5].is_emissive(),
                mats_[6].is_emissive(),
                mats_[7].is_emissive()
                );
    }

    spectrum<simd::float8> ambient() const
    {
        std::array<spectrum<float>, 8> amb;

        for (size_t i = 0; i < 8; ++i)
        {
            amb[i] = mats_[i].ambient();
        }

        return simd::pack(amb);
    }

    template <typename SR>
    spectrum<simd::float8> shade(SR const& sr) const
    {
        auto sr8 = unpack(sr);

        std::array<spectrum<float>, 8> shaded;

        for (size_t i = 0; i < 8; ++i)
        {
            shaded[i] = mats_[i].shade(sr8[i]);
        }

        return simd::pack(shaded);
    }

    template <typename SR, typename S /* sampler */>
    spectrum<simd::float8> sample(
            SR const&                   sr,
            vector<3, simd::float8>&    refl_dir,
            simd::float8&               pdf,
            S&                          samp
            ) const
    {
        using float_array = typename simd::aligned_array<simd::float8>::type;

        auto sr8 = unpack(sr);
        auto& s = samp.get_sampler();

        std::array<vector<3, float>, 8> rd8;
        float_array                     pdf8;
        std::array<spectrum<float>, 8>  sampled;

        for (size_t i = 0; i < 8; ++i)
        {
            sampled[i] = mats_[i].sample(sr8[i], rd8[i], pdf8[i], s);
        }

        refl_dir = simd::pack(rd8);
        pdf = simd::float8(pdf8);
        return simd::pack(sampled);
    }

private:

    std::array<single_material, 8> mats_;

};

#endif // VSNRAY_SIMD_ISA >= VSNRAY_SIMD_ISA_AVX

//-------------------------------------------------------------------------------------------------
// Pack and unpack
//

template <typename ...Ts>
inline generic_material<4, Ts...> pack(std::array<visionaray::generic_material<Ts...>, 4> const& mats)
{
    return generic_material<4, Ts...>(mats);
}

template <typename ...Ts>
inline std::array<visionaray::generic_material<Ts...>, 4> unpack(generic_material<4, Ts...> const& m4)
{
    return std::array<visionaray::generic_material<Ts...>, 4>{{ m4.get(0), m4.get(1), m4.get(2), m4.get(3) }};
}

#if VSNRAY_SIMD_ISA >= VSNRAY_SIMD_ISA_AVX

template <typename ...Ts>
inline generic_material<8, Ts...> pack(std::array<visionaray::generic_material<Ts...>, 8> const& mats)
{
    return generic_material<8, Ts...>(mats);
}

template <typename ...Ts>
inline std::array<visionaray::generic_material<Ts...>, 8> unpack(generic_material<8, Ts...> const& m8)
{
    return std::array<visionaray::generic_material<Ts...>, 8>{{
            m8.get(0), m8.get(1), m8.get(2), m8.get(3),
            m8.get(4), m8.get(5), m8.get(6), m8.get(7)
            }};
}

#endif // VSNRAY_SIMD_ISA >= VSNRAY_SIMD_ISA_AVX

} // simd
} // visionaray
<commit_msg>Less code duplication<commit_after>// This file is distributed under the MIT license.
// See the LICENSE file for details.

#include <array>
#include <cstddef>

#include <visionaray/material.h>

namespace visionaray
{

//-------------------------------------------------------------------------------------------------
// Public interface
//

template <typename T, typename ...Ts>
template <template <typename> class M>
inline generic_material<T, Ts...>::generic_material(M<typename T::scalar_type> const& material)
    : generic_material<T, Ts...>::base_type(material)
{
}

template <typename T, typename ...Ts>
VSNRAY_FUNC
inline bool generic_material<T, Ts...>::is_emissive() const
{
    return apply_visitor( is_emissive_visitor(), *this );
}

template <typename T, typename ...Ts>
VSNRAY_FUNC
inline spectrum<typename T::scalar_type> generic_material<T, Ts...>::ambient() const
{
    return apply_visitor( ambient_visitor(), *this );
}

template <typename T, typename ...Ts>
template <typename SR>
VSNRAY_FUNC
inline spectrum<typename SR::scalar_type> generic_material<T, Ts...>::shade(SR const& sr) const
{
    return apply_visitor( shade_visitor<SR>(sr), *this );
}

template <typename T, typename ...Ts>
template <typename SR, typename U, typename Sampler>
VSNRAY_FUNC
inline spectrum<U> generic_material<T, Ts...>::sample(
        SR const&       sr,
        vector<3, U>&   refl_dir,
        U&              pdf,
        Sampler&        sampler
        ) const
{
    return apply_visitor( sample_visitor<SR, U, Sampler>(sr, refl_dir, pdf, sampler), *this );
}

//-------------------------------------------------------------------------------------------------
// Private variant visitors
//

template <typename T, typename ...Ts>
struct generic_material<T, Ts...>::is_emissive_visitor
{
    using Base = generic_material<T, Ts...>;
    using return_type = bool;

    template <typename X>
    VSNRAY_FUNC
    bool operator()(X) const
    {
        return false;
    }

    VSNRAY_FUNC
    bool operator()(emissive<typename Base::scalar_type>) const
    {
        return true;
    }
};

template <typename T, typename ...Ts>
struct generic_material<T, Ts...>::ambient_visitor
{
    using Base = generic_material<T, Ts...>;
    using return_type = spectrum<typename Base::scalar_type>;

    template <typename X>
    VSNRAY_FUNC
    return_type operator()(X const& ref) const
    {
        return ref.ambient();
    }
};

template <typename T, typename ...Ts>
template <typename SR>
struct generic_material<T, Ts...>::shade_visitor
{
    using return_type = spectrum<typename SR::scalar_type>;

    VSNRAY_FUNC
    shade_visitor(SR const& sr) : sr_(sr) {}

    template <typename X>
    VSNRAY_FUNC
    return_type operator()(X const& ref) const
    {
        return ref.shade(sr_);
    }

    SR const& sr_;
};

template <typename T, typename ...Ts>
template <typename SR, typename U, typename Sampler>
struct generic_material<T, Ts...>::sample_visitor
{
    using return_type = spectrum<typename SR::scalar_type>;

    VSNRAY_FUNC
    sample_visitor(SR const& sr, vector<3, U>& refl_dir, U& pdf, Sampler& sampler)
        : sr_(sr)
        , refl_dir_(refl_dir)
        , pdf_(pdf)
        , sampler_(sampler)
    {
    }

    template <typename X>
    VSNRAY_FUNC
    return_type operator()(X const& ref) const
    {
        return ref.sample(sr_, refl_dir_, pdf_, sampler_);
    }

    SR const&       sr_;
    vector<3, U>&   refl_dir_;
    U&              pdf_;
    Sampler&        sampler_;
};

namespace simd
{

//-------------------------------------------------------------------------------------------------
// SIMD type used internally. Contains N generic materials
//

template <size_t N, typename ...Ts>
class generic_material
{
public:

    using scalar_type      = typename float_from_simd_width<N>::type;
    using single_material  = visionaray::generic_material<Ts...>;

public:

    generic_material(std::array<single_material, N> const& mats)
        : mats_(mats)
    {
    }

    single_material& get(int i)
    {
        return mats_[i];
    }

    single_material const& get(int i) const
    {
        return mats_[i];
    }

    typename mask_type<scalar_type>::type is_emissive() const
    {
        using mask_t = typename mask_type<scalar_type>::type;
        using mask_array = typename aligned_array<mask_t>::type;

        mask_array arr;

        for (size_t i = 0; i < 4; ++i)
        {
            arr[i] = mats_[i].is_emissive();
        }

        return mask_t(arr);
    }

    spectrum<scalar_type> ambient() const
    {
        std::array<spectrum<float>, N> amb;

        for (size_t i = 0; i < N; ++i)
        {
            amb[i] = mats_[i].ambient();
        }

        return pack(amb);
    }

    template <typename SR>
    spectrum<scalar_type> shade(SR const& sr) const
    {
        auto srs = unpack(sr);

        std::array<spectrum<float>, N> shaded;

        for (size_t i = 0; i < N; ++i)
        {
            shaded[i] = mats_[i].shade(srs[i]);
        }

        return pack(shaded);
    }

    template <typename SR, typename S /* sampler */>
    spectrum<simd::float4> sample(
            SR const&               sr,
            vector<3, scalar_type>& refl_dir,
            simd::float4&           pdf,
            S&                      samp
            ) const
    {
        using float_array = typename aligned_array<scalar_type>::type;

        auto srs = unpack(sr);
        auto& s = samp.get_sampler();

        std::array<vector<3, float>, N> rds;
        float_array                     pdfs;
        std::array<spectrum<float>, N>  sampled;

        for (size_t i = 0; i < N; ++i)
        {
            sampled[i] = mats_[i].sample(srs[i], rds[i], pdfs[i], s);
        }

        refl_dir = pack(rds);
        pdf = scalar_type(pdfs);
        return pack(sampled);
    }

private:

    std::array<single_material, N> mats_;

};

//-------------------------------------------------------------------------------------------------
// Pack and unpack
//

template <typename ...Ts>
inline generic_material<4, Ts...> pack(std::array<visionaray::generic_material<Ts...>, 4> const& mats)
{
    return generic_material<4, Ts...>(mats);
}

template <typename ...Ts>
inline std::array<visionaray::generic_material<Ts...>, 4> unpack(generic_material<4, Ts...> const& m4)
{
    return std::array<visionaray::generic_material<Ts...>, 4>{{ m4.get(0), m4.get(1), m4.get(2), m4.get(3) }};
}

#if VSNRAY_SIMD_ISA >= VSNRAY_SIMD_ISA_AVX

template <typename ...Ts>
inline generic_material<8, Ts...> pack(std::array<visionaray::generic_material<Ts...>, 8> const& mats)
{
    return generic_material<8, Ts...>(mats);
}

template <typename ...Ts>
inline std::array<visionaray::generic_material<Ts...>, 8> unpack(generic_material<8, Ts...> const& m8)
{
    return std::array<visionaray::generic_material<Ts...>, 8>{{
            m8.get(0), m8.get(1), m8.get(2), m8.get(3),
            m8.get(4), m8.get(5), m8.get(6), m8.get(7)
            }};
}

#endif // VSNRAY_SIMD_ISA >= VSNRAY_SIMD_ISA_AVX

} // simd
} // visionaray
<|endoftext|>


<commit_before>/*
 * Copyright 2018 Google Inc.
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#include "gm.h"
#include "SkFont.h"
#include "SkPath.h"

// This GM shows off a flaw in delta-based rasterizers (DAA, CCPR, etc.).
// See also the bottom of dashing4 and skia:6886.

static const int K = 50;

DEF_SIMPLE_GM(daa, canvas, K+350, K) {
    SkPaint paint;
    paint.setAntiAlias(true);

    paint.setColor(SK_ColorBLACK);
    canvas->drawString("Should be a green square with no red showing through.",
                       K*1.5f, K/2, SkFont(), paint);

    paint.setColor(SK_ColorRED);
    canvas->drawRect({0,0,K,K}, paint);

    SkPath path;
    SkPoint tri1[] = {{0,0},{K,K},{0,K},{0,0}};
    SkPoint tri2[] = {{0,0},{K,K},{K,0},{0,0}};
    path.addPoly(tri1, SK_ARRAY_COUNT(tri1), false);
    path.addPoly(tri2, SK_ARRAY_COUNT(tri2), false);

    paint.setColor(SK_ColorGREEN);
    canvas->drawPath(path, paint);
}
<commit_msg>add more test cases to DAA gm<commit_after>/*
 * Copyright 2018 Google Inc.
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#include "gm.h"
#include "SkFont.h"
#include "SkPath.h"

// This GM shows off a flaw in delta-based rasterizers (DAA, CCPR, etc.).
// See also the bottom of dashing4 and skia:6886.

static const int K = 49;

DEF_SIMPLE_GM(daa, canvas, K+350, 5*K) {
    SkPaint paint;
    paint.setAntiAlias(true);

    {
        paint.setColor(SK_ColorBLACK);
        canvas->drawString("Should be a green square with no red showing through.",
                           K*1.5f, K*0.5f, SkFont(), paint);

        paint.setColor(SK_ColorRED);
        canvas->drawRect({0,0,K,K}, paint);

        SkPath path;
        SkPoint tri1[] = {{0,0},{K,K},{0,K},{0,0}};
        SkPoint tri2[] = {{0,0},{K,K},{K,0},{0,0}};
        path.addPoly(tri1, SK_ARRAY_COUNT(tri1), false);
        path.addPoly(tri2, SK_ARRAY_COUNT(tri2), false);

        paint.setColor(SK_ColorGREEN);
        canvas->drawPath(path, paint);
    }

    canvas->translate(0,K);
    {
        paint.setColor(SK_ColorBLACK);
        canvas->drawString("Adjacent rects, two draws.  Blue then green, no red?",
                           K*1.5f, K*0.5f, SkFont(), paint);

        paint.setColor(SK_ColorRED);
        canvas->drawRect({0,0,K,K}, paint);

        {
            SkPath path;
            SkPoint rect1[] = {{0,0},{0,K},{K*0.5f,K},{K*0.5f,0}};
            path.addPoly(rect1, SK_ARRAY_COUNT(rect1), false);

            paint.setColor(SK_ColorBLUE);
            canvas->drawPath(path, paint);
        }

        {
            SkPath path;
            SkPoint rect2[] = {{K*0.5f,0},{K*0.5f,K},{K,K},{K,0}};
            path.addPoly(rect2, SK_ARRAY_COUNT(rect2), false);

            paint.setColor(SK_ColorGREEN);
            canvas->drawPath(path, paint);
        }
    }

    canvas->translate(0,K);
    {
        paint.setColor(SK_ColorBLACK);
        canvas->drawString("Adjacent rects, wound together.  All green?",
                           K*1.5f, K*0.5f, SkFont(), paint);

        paint.setColor(SK_ColorRED);
        canvas->drawRect({0,0,K,K}, paint);

        {
            SkPath path;
            SkPoint rect1[] = {{0,0},{0,K},{K*0.5f,K},{K*0.5f,0}};
            SkPoint rect2[] = {{K*0.5f,0},{K*0.5f,K},{K,K},{K,0}};

            path.addPoly(rect1, SK_ARRAY_COUNT(rect1), false);
            path.addPoly(rect2, SK_ARRAY_COUNT(rect2), false);

            paint.setColor(SK_ColorGREEN);
            canvas->drawPath(path, paint);
        }
    }

    canvas->translate(0,K);
    {
        paint.setColor(SK_ColorBLACK);
        canvas->drawString("Adjacent rects, wound opposite.  All green?",
                           K*1.5f, K*0.5f, SkFont(), paint);

        paint.setColor(SK_ColorRED);
        canvas->drawRect({0,0,K,K}, paint);

        {
            SkPath path;
            SkPoint rect1[] = {{0,0},{0,K},{K*0.5f,K},{K*0.5f,0}};
            SkPoint rect2[] = {{K*0.5f,0},{K,0},{K,K},{K*0.5f,K}};

            path.addPoly(rect1, SK_ARRAY_COUNT(rect1), false);
            path.addPoly(rect2, SK_ARRAY_COUNT(rect2), false);

            paint.setColor(SK_ColorGREEN);
            canvas->drawPath(path, paint);
        }
    }

    canvas->translate(0,K);
    {
        paint.setColor(SK_ColorBLACK);
        canvas->drawString("One poly, wound opposite.  All green?",
                           K*1.5f, K*0.5f, SkFont(), paint);

        paint.setColor(SK_ColorRED);
        canvas->drawRect({0,0,K,K}, paint);

        {
            SkPath path;
            SkPoint poly[] = {{K*0.5f,0},{0,0},{0,K},{K*0.5f,K},{K*0.5f,0},{K,0},{K,K},{K*0.5f,K}};

            path.addPoly(poly, SK_ARRAY_COUNT(poly), false);

            paint.setColor(SK_ColorGREEN);
            canvas->drawPath(path, paint);
        }
    }
}
<|endoftext|>


<commit_before>#include "gnucash.h"
#include "journal.h"
#include "format.h"
#include "error.h"
#include "acconf.h"

#include <iostream>
#include <sstream>
#include <cstring>

extern "C" {
#if defined(HAVE_EXPAT)
#include <expat.h>           // expat XML parser
#elif defined(HAVE_XMLPARSE)
#include <xmlparse.h>        // expat XML parser
#else
#error "No XML parser library defined."
#endif
}

namespace ledger {

typedef std::map<const std::string, account_t *>  accounts_map;
typedef std::pair<const std::string, account_t *> accounts_pair;

typedef std::map<account_t *, commodity_t *>  account_comm_map;
typedef std::pair<account_t *, commodity_t *> account_comm_pair;

static journal_t *	curr_journal;
static account_t *	master_account;
static account_t *	curr_account;
static std::string	curr_account_id;
static entry_t *	curr_entry;
static commodity_t *	entry_comm;
static commodity_t *	curr_comm;
static amount_t		curr_value;
static amount_t		curr_quant;
static XML_Parser	current_parser;
static accounts_map	accounts_by_id;
static account_comm_map	account_comms;
static unsigned int	count;
static std::string	have_error;

static std::istream *   instreamp;
static unsigned int     offset;
static XML_Parser       parser;
static std::string      path;
static unsigned int     src_idx;
static istream_pos_type beg_pos;
static unsigned long    beg_line;

static transaction_t::state_t curr_state;

static enum action_t {
  NO_ACTION,
  ACCOUNT_NAME,
  ACCOUNT_ID,
  ACCOUNT_PARENT,
  COMM_SYM,
  COMM_NAME,
  COMM_PREC,
  ENTRY_NUM,
  ALMOST_ENTRY_DATE,
  ENTRY_DATE,
  ENTRY_DESC,
  XACT_STATE,
  XACT_AMOUNT,
  XACT_VALUE,
  XACT_QUANTITY,
  XACT_ACCOUNT,
  XACT_NOTE
} action;

static void startElement(void *userData, const char *name, const char **atts)
{
  if (std::strcmp(name, "gnc:account") == 0) {
    curr_account = new account_t(master_account);
  }
  else if (std::strcmp(name, "act:name") == 0)
    action = ACCOUNT_NAME;
  else if (std::strcmp(name, "act:id") == 0)
    action = ACCOUNT_ID;
  else if (std::strcmp(name, "act:parent") == 0)
    action = ACCOUNT_PARENT;
  else if (std::strcmp(name, "gnc:commodity") == 0) {
    assert(! curr_comm);
    curr_comm = new commodity_t("");
  }
  else if (std::strcmp(name, "cmdty:id") == 0)
    action = COMM_SYM;
  else if (std::strcmp(name, "cmdty:name") == 0)
    action = COMM_NAME;
  else if (std::strcmp(name, "cmdty:fraction") == 0)
    action = COMM_PREC;
  else if (std::strcmp(name, "gnc:transaction") == 0) {
    assert(! curr_entry);
    curr_entry = new entry_t;
  }
  else if (std::strcmp(name, "trn:num") == 0)
    action = ENTRY_NUM;
  else if (std::strcmp(name, "trn:date-posted") == 0)
    action = ALMOST_ENTRY_DATE;
  else if (action == ALMOST_ENTRY_DATE && std::strcmp(name, "ts:date") == 0)
    action = ENTRY_DATE;
  else if (std::strcmp(name, "trn:description") == 0)
    action = ENTRY_DESC;
  else if (std::strcmp(name, "trn:split") == 0) {
    assert(curr_entry);
    curr_entry->add_transaction(new transaction_t(curr_account));
  }
  else if (std::strcmp(name, "split:reconciled-state") == 0)
    action = XACT_STATE;
  else if (std::strcmp(name, "split:amount") == 0)
    action = XACT_AMOUNT;
  else if (std::strcmp(name, "split:value") == 0)
    action = XACT_VALUE;
  else if (std::strcmp(name, "split:quantity") == 0)
    action = XACT_QUANTITY;
  else if (std::strcmp(name, "split:account") == 0)
    action = XACT_ACCOUNT;
  else if (std::strcmp(name, "split:memo") == 0)
    action = XACT_NOTE;
}

static void endElement(void *userData, const char *name)
{
  if (std::strcmp(name, "gnc:account") == 0) {
    assert(curr_account);
    if (curr_account->parent == master_account)
      curr_journal->add_account(curr_account);
    accounts_by_id.insert(accounts_pair(curr_account_id, curr_account));
    curr_account = NULL;
  }
  else if (std::strcmp(name, "gnc:commodity") == 0) {
    assert(curr_comm);
    commodity_t::add_commodity(curr_comm);
    curr_comm = NULL;
  }
  else if (std::strcmp(name, "gnc:transaction") == 0) {
    assert(curr_entry);
    if (! curr_journal->add_entry(curr_entry)) {
      print_entry(std::cerr, *curr_entry);
      have_error = "The above entry does not balance";
      delete curr_entry;
    } else {
      curr_entry->src_idx  = src_idx;
      curr_entry->beg_pos  = beg_pos;
      curr_entry->beg_line = beg_line;
      curr_entry->end_pos  = instreamp->tellg();
      curr_entry->end_line = XML_GetCurrentLineNumber(parser) - offset;
      count++;
    }
    curr_entry = NULL;
  }
  action = NO_ACTION;
}

static amount_t convert_number(const std::string& number,
			       int * precision = NULL)
{
  const char * num = number.c_str();

  if (char * p = std::strchr(num, '/')) {
    std::string numer_str(num, p - num);
    std::string denom_str(p + 1);

    amount_t amt(numer_str);
    amount_t den(denom_str);

    if (precision)
      *precision = denom_str.length() - 1;

    if (! den) {
      have_error = "Denominator in entry is zero!";
      return amt;
    } else {
      return amt / den;
    }
  } else {
    return amount_t(number);
  }
}

static void dataHandler(void *userData, const char *s, int len)
{
  switch (action) {
  case ACCOUNT_NAME:
    curr_account->name = std::string(s, len);
    break;

  case ACCOUNT_ID:
    curr_account_id = std::string(s, len);
    break;

  case ACCOUNT_PARENT: {
    accounts_map::iterator i = accounts_by_id.find(std::string(s, len));
    assert(i != accounts_by_id.end());
    curr_account->parent = (*i).second;
    curr_account->depth  = curr_account->parent->depth + 1;
    (*i).second->add_account(curr_account);
    break;
  }

  case COMM_SYM:
    if (curr_comm) {
      curr_comm->set_symbol(std::string(s, len));
    }
    else if (curr_account) {
      std::string symbol(s, len);
      commodity_t * comm = commodity_t::find_commodity(symbol, true);
      if (symbol != "$" && symbol != "USD")
	comm->flags |= COMMODITY_STYLE_SEPARATED;
      account_comms.insert(account_comm_pair(curr_account, comm));
    }
    else if (curr_entry) {
      std::string symbol(s, len);
      entry_comm = commodity_t::find_commodity(symbol, true);
      if (symbol != "$" && symbol != "USD")
	entry_comm->flags |= COMMODITY_STYLE_SEPARATED;
    }
    break;

  case COMM_NAME:
    curr_comm->name = std::string(s, len);
    break;

  case COMM_PREC:
    curr_comm->precision = len - 1;
    break;

  case ENTRY_NUM:
    curr_entry->code = std::string(s, len);
    break;

  case ENTRY_DATE: {
    struct tm when;
    strptime(std::string(s, len).c_str(), "%Y-%m-%d %H:%M:%S %z", &when);
    curr_entry->_date = std::mktime(&when);
    break;
  }

  case ENTRY_DESC:
    curr_entry->payee = std::string(s, len);
    break;

  case XACT_STATE:
    if (*s == 'y')
      curr_state = transaction_t::PENDING;
    else
      curr_state = transaction_t::CLEARED;
    break;

  case XACT_VALUE: {
    int precision;
    assert(entry_comm);
    curr_value = convert_number(std::string(s, len), &precision);
    curr_value.set_commodity(*entry_comm);

    if (precision > entry_comm->precision)
      entry_comm->precision = precision;
    break;
  }

  case XACT_QUANTITY:
    curr_quant = convert_number(std::string(s, len));
    break;

  case XACT_ACCOUNT: {
    transaction_t * xact = curr_entry->transactions.back();

    accounts_map::iterator i = accounts_by_id.find(std::string(s, len));
    if (i != accounts_by_id.end()) {
      xact->account = (*i).second;
    } else {
      xact->account = curr_journal->find_account("<Unknown>");

      have_error = (std::string("Could not find account ") +
		    std::string(s, len));
    }

    amount_t value;

    account_comm_map::iterator ac = account_comms.find(xact->account);
    if (ac != account_comms.end()) {
      commodity_t * default_commodity = (*ac).second;

      curr_quant.set_commodity(*default_commodity);
      value = curr_quant.round(default_commodity->precision);

      if (curr_value.commodity() == *default_commodity)
	curr_value = value;
    } else {
      value = curr_quant;
    }

    xact->state  = curr_state;
    xact->amount = value;
    if (value != curr_value)
      xact->cost = new amount_t(curr_value);

    curr_state = transaction_t::UNCLEARED;
    break;
  }

  case XACT_NOTE:
    curr_entry->transactions.back()->note = std::string(s, len);
    break;

  case NO_ACTION:
  case ALMOST_ENTRY_DATE:
  case XACT_AMOUNT:
    break;

  default:
    assert(0);
    break;
  }
}

bool gnucash_parser_t::test(std::istream& in) const
{
  char buf[5];
  in.read(buf, 5);
  in.seekg(0, std::ios::beg);

  return std::strncmp(buf, "<?xml", 5) == 0;
}

unsigned int gnucash_parser_t::parse(std::istream&	 in,
				     journal_t *	 journal,
				     account_t *	 master,
				     const std::string * original_file)
{
  char buf[BUFSIZ];

  count		 = 0;
  action	 = NO_ACTION;
  curr_journal	 = journal;
  master_account = master ? master : journal->master;
  curr_account	 = NULL;
  curr_entry	 = NULL;
  curr_comm	 = NULL;
  entry_comm	 = NULL;
  curr_state	 = transaction_t::UNCLEARED;

  instreamp = ∈
  path	    = original_file ? *original_file : "<gnucash>";
  src_idx   = journal->sources.size() - 1;

  // GnuCash uses the USD commodity without defining it, which really
  // means $.
  commodity_t * usd;
  usd = new commodity_t("$", 2, COMMODITY_STYLE_THOUSANDS);
  commodity_t::add_commodity(usd, "$");
  usd = new commodity_t("$", 2, COMMODITY_STYLE_THOUSANDS);
  commodity_t::add_commodity(usd, "USD");

  offset = 2;
  parser = current_parser = XML_ParserCreate(NULL);

  XML_SetElementHandler(parser, startElement, endElement);
  XML_SetCharacterDataHandler(parser, dataHandler);

  while (in.good() && ! in.eof()) {
    beg_pos  = in.tellg();
    beg_line = (XML_GetCurrentLineNumber(parser) - offset) + 1;

    in.getline(buf, BUFSIZ - 1);
    std::strcat(buf, "\n");
    if (! XML_Parse(parser, buf, std::strlen(buf), in.eof())) {
      unsigned long line = XML_GetCurrentLineNumber(parser) - offset++;
      const char *  msg  = XML_ErrorString(XML_GetErrorCode(parser));
      XML_ParserFree(parser);
      throw parse_error(path, line, msg);
    }

    if (! have_error.empty()) {
      unsigned long line = XML_GetCurrentLineNumber(parser) - offset++;
      parse_error err(path, line, have_error);
      std::cerr << "Error: " << err.what() << std::endl;
      have_error = "";
    }
  }

  XML_ParserFree(parser);

  accounts_by_id.clear();
  curr_account_id.clear();

  return count;
}

} // namespace ledger

#ifdef USE_BOOST_PYTHON

#include <boost/python.hpp>

using namespace boost::python;
using namespace ledger;

BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS(gnucash_parse_overloads,
				       gnucash_parser_t::parse, 2, 4)

void export_gnucash() {
  class_< gnucash_parser_t, bases<parser_t> > ("GnucashParser")
    .def("test", &gnucash_parser_t::test)
    .def("parse", &gnucash_parser_t::parse, gnucash_parse_overloads())
    ;
}

#endif // USE_BOOST_PYTHON
<commit_msg>(endElement): Changed the parser a bit to always prefer the transaction commodity over the account commodity.<commit_after>#include "gnucash.h"
#include "journal.h"
#include "format.h"
#include "error.h"
#include "acconf.h"

#include <iostream>
#include <sstream>
#include <cstring>

extern "C" {
#if defined(HAVE_EXPAT)
#include <expat.h>           // expat XML parser
#elif defined(HAVE_XMLPARSE)
#include <xmlparse.h>        // expat XML parser
#else
#error "No XML parser library defined."
#endif
}

namespace ledger {

typedef std::map<const std::string, account_t *>  accounts_map;
typedef std::pair<const std::string, account_t *> accounts_pair;

typedef std::map<account_t *, commodity_t *>  account_comm_map;
typedef std::pair<account_t *, commodity_t *> account_comm_pair;

static journal_t *	curr_journal;
static account_t *	master_account;
static account_t *	curr_account;
static std::string	curr_account_id;
static entry_t *	curr_entry;
static commodity_t *	entry_comm;
static commodity_t *	curr_comm;
static amount_t		curr_value;
static amount_t		curr_quant;
static XML_Parser	current_parser;
static accounts_map	accounts_by_id;
static account_comm_map	account_comms;
static unsigned int	count;
static std::string	have_error;

static std::istream *   instreamp;
static unsigned int     offset;
static XML_Parser       parser;
static std::string      path;
static unsigned int     src_idx;
static istream_pos_type beg_pos;
static unsigned long    beg_line;

static transaction_t::state_t curr_state;

static enum action_t {
  NO_ACTION,
  ACCOUNT_NAME,
  ACCOUNT_ID,
  ACCOUNT_PARENT,
  COMM_SYM,
  COMM_NAME,
  COMM_PREC,
  ENTRY_NUM,
  ALMOST_ENTRY_DATE,
  ENTRY_DATE,
  ENTRY_DESC,
  XACT_STATE,
  XACT_AMOUNT,
  XACT_VALUE,
  XACT_QUANTITY,
  XACT_ACCOUNT,
  XACT_NOTE
} action;

static void startElement(void *userData, const char *name, const char **atts)
{
  if (std::strcmp(name, "gnc:account") == 0) {
    curr_account = new account_t(master_account);
  }
  else if (std::strcmp(name, "act:name") == 0)
    action = ACCOUNT_NAME;
  else if (std::strcmp(name, "act:id") == 0)
    action = ACCOUNT_ID;
  else if (std::strcmp(name, "act:parent") == 0)
    action = ACCOUNT_PARENT;
  else if (std::strcmp(name, "gnc:commodity") == 0) {
    assert(! curr_comm);
    curr_comm = new commodity_t("");
  }
  else if (std::strcmp(name, "cmdty:id") == 0)
    action = COMM_SYM;
  else if (std::strcmp(name, "cmdty:name") == 0)
    action = COMM_NAME;
  else if (std::strcmp(name, "cmdty:fraction") == 0)
    action = COMM_PREC;
  else if (std::strcmp(name, "gnc:transaction") == 0) {
    assert(! curr_entry);
    curr_entry = new entry_t;
  }
  else if (std::strcmp(name, "trn:num") == 0)
    action = ENTRY_NUM;
  else if (std::strcmp(name, "trn:date-posted") == 0)
    action = ALMOST_ENTRY_DATE;
  else if (action == ALMOST_ENTRY_DATE && std::strcmp(name, "ts:date") == 0)
    action = ENTRY_DATE;
  else if (std::strcmp(name, "trn:description") == 0)
    action = ENTRY_DESC;
  else if (std::strcmp(name, "trn:split") == 0) {
    assert(curr_entry);
    curr_entry->add_transaction(new transaction_t(curr_account));
  }
  else if (std::strcmp(name, "split:reconciled-state") == 0)
    action = XACT_STATE;
  else if (std::strcmp(name, "split:amount") == 0)
    action = XACT_AMOUNT;
  else if (std::strcmp(name, "split:value") == 0)
    action = XACT_VALUE;
  else if (std::strcmp(name, "split:quantity") == 0)
    action = XACT_QUANTITY;
  else if (std::strcmp(name, "split:account") == 0)
    action = XACT_ACCOUNT;
  else if (std::strcmp(name, "split:memo") == 0)
    action = XACT_NOTE;
}

static void endElement(void *userData, const char *name)
{
  if (std::strcmp(name, "gnc:account") == 0) {
    assert(curr_account);
    if (curr_account->parent == master_account)
      curr_journal->add_account(curr_account);
    accounts_by_id.insert(accounts_pair(curr_account_id, curr_account));
    curr_account = NULL;
  }
  else if (std::strcmp(name, "gnc:commodity") == 0) {
    assert(curr_comm);
    commodity_t::add_commodity(curr_comm);
    curr_comm = NULL;
  }
  else if (std::strcmp(name, "gnc:transaction") == 0) {
    assert(curr_entry);

    // Add the new entry (what gnucash calls a 'transaction') to the
    // journal
    if (! curr_journal->add_entry(curr_entry)) {
      print_entry(std::cerr, *curr_entry);
      have_error = "The above entry does not balance";
      delete curr_entry;
    } else {
      curr_entry->src_idx  = src_idx;
      curr_entry->beg_pos  = beg_pos;
      curr_entry->beg_line = beg_line;
      curr_entry->end_pos  = instreamp->tellg();
      curr_entry->end_line = XML_GetCurrentLineNumber(parser) - offset;
      count++;
    }

    // Clear the relevant variables for the next run
    curr_entry = NULL;
    entry_comm = NULL;
  }
  else if (std::strcmp(name, "trn:split") == 0) {
    transaction_t * xact = curr_entry->transactions.back();

    // Identify the commodity to use for the value of this
    // transaction.  The quantity indicates how many times that value
    // the transaction is worth.
    amount_t value;
    commodity_t * default_commodity = NULL;
    if (entry_comm) {
      default_commodity = entry_comm;
    } else {
      account_comm_map::iterator ac = account_comms.find(xact->account);
      if (ac != account_comms.end())
	default_commodity = (*ac).second;
    }

    if (default_commodity) {
      curr_quant.set_commodity(*default_commodity);
      value = curr_quant.round(default_commodity->precision);

      if (curr_value.commodity() == *default_commodity)
	curr_value = value;
    } else {
      value = curr_quant;
    }

    xact->state  = curr_state;
    xact->amount = value;
    if (value != curr_value)
      xact->cost = new amount_t(curr_value);

    // Clear the relevant variables for the next run
    curr_state = transaction_t::UNCLEARED;
    curr_value = amount_t();
    curr_quant = amount_t();
  }

  action = NO_ACTION;
}

static amount_t convert_number(const std::string& number,
			       int * precision = NULL)
{
  const char * num = number.c_str();

  if (char * p = std::strchr(num, '/')) {
    std::string numer_str(num, p - num);
    std::string denom_str(p + 1);

    amount_t amt(numer_str);
    amount_t den(denom_str);

    if (precision)
      *precision = denom_str.length() - 1;

    if (! den) {
      have_error = "Denominator in entry is zero!";
      return amt;
    } else {
      return amt / den;
    }
  } else {
    return amount_t(number);
  }
}

static void dataHandler(void *userData, const char *s, int len)
{
  switch (action) {
  case ACCOUNT_NAME:
    curr_account->name = std::string(s, len);
    break;

  case ACCOUNT_ID:
    curr_account_id = std::string(s, len);
    break;

  case ACCOUNT_PARENT: {
    accounts_map::iterator i = accounts_by_id.find(std::string(s, len));
    assert(i != accounts_by_id.end());
    curr_account->parent = (*i).second;
    curr_account->depth  = curr_account->parent->depth + 1;
    (*i).second->add_account(curr_account);
    break;
  }

  case COMM_SYM:
    if (curr_comm) {
      curr_comm->set_symbol(std::string(s, len));
    }
    else if (curr_account) {
      std::string symbol(s, len);
      commodity_t * comm = commodity_t::find_commodity(symbol, true);
      if (symbol != "$" && symbol != "USD")
	comm->flags |= COMMODITY_STYLE_SEPARATED;
      account_comms.insert(account_comm_pair(curr_account, comm));
    }
    else if (curr_entry) {
      std::string symbol(s, len);
      entry_comm = commodity_t::find_commodity(symbol, true);
      if (symbol != "$" && symbol != "USD")
	entry_comm->flags |= COMMODITY_STYLE_SEPARATED;
    }
    break;

  case COMM_NAME:
    curr_comm->name = std::string(s, len);
    break;

  case COMM_PREC:
    curr_comm->precision = len - 1;
    break;

  case ENTRY_NUM:
    curr_entry->code = std::string(s, len);
    break;

  case ENTRY_DATE: {
    struct tm when;
    strptime(std::string(s, len).c_str(), "%Y-%m-%d %H:%M:%S %z", &when);
    curr_entry->_date = std::mktime(&when);
    break;
  }

  case ENTRY_DESC:
    curr_entry->payee = std::string(s, len);
    break;

  case XACT_STATE:
    if (*s == 'y')
      curr_state = transaction_t::CLEARED;
    else if (*s == 'n')
      curr_state = transaction_t::UNCLEARED;
    else
      curr_state = transaction_t::PENDING;
    break;

  case XACT_VALUE: {
    int precision;
    assert(entry_comm);
    curr_value = convert_number(std::string(s, len), &precision);
    curr_value.set_commodity(*entry_comm);

    if (precision > entry_comm->precision)
      entry_comm->precision = precision;
    break;
  }

  case XACT_QUANTITY:
    curr_quant = convert_number(std::string(s, len));
    break;

  case XACT_ACCOUNT: {
    transaction_t * xact = curr_entry->transactions.back();

    accounts_map::iterator i = accounts_by_id.find(std::string(s, len));
    if (i != accounts_by_id.end()) {
      xact->account = (*i).second;
    } else {
      xact->account = curr_journal->find_account("<Unknown>");

      have_error = (std::string("Could not find account ") +
		    std::string(s, len));
    }
    break;
  }

  case XACT_NOTE:
    curr_entry->transactions.back()->note = std::string(s, len);
    break;

  case NO_ACTION:
  case ALMOST_ENTRY_DATE:
  case XACT_AMOUNT:
    break;

  default:
    assert(0);
    break;
  }
}

bool gnucash_parser_t::test(std::istream& in) const
{
  char buf[5];
  in.read(buf, 5);
  in.seekg(0, std::ios::beg);

  return std::strncmp(buf, "<?xml", 5) == 0;
}

unsigned int gnucash_parser_t::parse(std::istream&	 in,
				     journal_t *	 journal,
				     account_t *	 master,
				     const std::string * original_file)
{
  char buf[BUFSIZ];

  count		 = 0;
  action	 = NO_ACTION;
  curr_journal	 = journal;
  master_account = master ? master : journal->master;
  curr_account	 = NULL;
  curr_entry	 = NULL;
  curr_comm	 = NULL;
  entry_comm	 = NULL;
  curr_state	 = transaction_t::UNCLEARED;

  instreamp = ∈
  path	    = original_file ? *original_file : "<gnucash>";
  src_idx   = journal->sources.size() - 1;

  // GnuCash uses the USD commodity without defining it, which really
  // means $.
  commodity_t * usd;
  usd = new commodity_t("$", 2, COMMODITY_STYLE_THOUSANDS);
  commodity_t::add_commodity(usd, "$");
  usd = new commodity_t("$", 2, COMMODITY_STYLE_THOUSANDS);
  commodity_t::add_commodity(usd, "USD");

  offset = 2;
  parser = current_parser = XML_ParserCreate(NULL);

  XML_SetElementHandler(parser, startElement, endElement);
  XML_SetCharacterDataHandler(parser, dataHandler);

  while (in.good() && ! in.eof()) {
    beg_pos  = in.tellg();
    beg_line = (XML_GetCurrentLineNumber(parser) - offset) + 1;

    in.getline(buf, BUFSIZ - 1);
    std::strcat(buf, "\n");
    if (! XML_Parse(parser, buf, std::strlen(buf), in.eof())) {
      unsigned long line = XML_GetCurrentLineNumber(parser) - offset++;
      const char *  msg  = XML_ErrorString(XML_GetErrorCode(parser));
      XML_ParserFree(parser);
      throw parse_error(path, line, msg);
    }

    if (! have_error.empty()) {
      unsigned long line = XML_GetCurrentLineNumber(parser) - offset++;
      parse_error err(path, line, have_error);
      std::cerr << "Error: " << err.what() << std::endl;
      have_error = "";
    }
  }

  XML_ParserFree(parser);

  accounts_by_id.clear();
  curr_account_id.clear();

  return count;
}

} // namespace ledger

#ifdef USE_BOOST_PYTHON

#include <boost/python.hpp>

using namespace boost::python;
using namespace ledger;

BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS(gnucash_parse_overloads,
				       gnucash_parser_t::parse, 2, 4)

void export_gnucash() {
  class_< gnucash_parser_t, bases<parser_t> > ("GnucashParser")
    .def("test", &gnucash_parser_t::test)
    .def("parse", &gnucash_parser_t::parse, gnucash_parse_overloads())
    ;
}

#endif // USE_BOOST_PYTHON
<|endoftext|>


<commit_before>// -------------------------------------------------------------------------
//    @FileName      :    NFCPluginManager.cpp
//    @Author           :    LvSheng.Huang
//    @Date             :    2012-12-15
//    @Module           :    NFCPluginManager
//
// -------------------------------------------------------------------------

#include "NFCPluginManager.h"
#include "NFComm/RapidXML/rapidxml.hpp"
#include "NFComm/RapidXML/rapidxml_iterators.hpp"
#include "NFComm/RapidXML/rapidxml_print.hpp"
#include "NFComm/RapidXML/rapidxml_utils.hpp"
#include "NFComm/NFPluginModule/NFIPlugin.h"
#include "NFComm/NFPluginModule/NFIActorDataModule.h"
#include "NFComm/NFPluginModule/NFPlatform.h"

#pragma comment( lib, "ws2_32.lib" )

#ifdef NF_DEBUG_MODE

#if NF_PLATFORM == NF_PLATFORM_WIN
#pragma comment( lib, "Theron_d.lib" )
#elif NF_PLATFORM == NF_PLATFORM_LINUX || NF_PLATFORM == NF_PLATFORM_ANDROID
#pragma comment( lib, "Theron_d.a" )
#elif NF_PLATFORM == NF_PLATFORM_APPLE || NF_PLATFORM == NF_PLATFORM_APPLE_IOS
#pragma comment( lib, "Theron_d.a" )
#endif

#else

#if NF_PLATFORM == NF_PLATFORM_WIN
#pragma comment( lib, "Theron.lib" )
#elif NF_PLATFORM == NF_PLATFORM_LINUX || NF_PLATFORM == NF_PLATFORM_ANDROID
#pragma comment( lib, "Theron.a" )
#elif NF_PLATFORM == NF_PLATFORM_APPLE || NF_PLATFORM == NF_PLATFORM_APPLE_IOS
#pragma comment( lib, "Theron.a" )
#endif

#endif

bool NFCPluginManager::LoadPlugin()
{
    rapidxml::file<> fdoc("Plugin.xml");
    rapidxml::xml_document<>  doc;
    doc.parse<0>(fdoc.data());

    rapidxml::xml_node<>* pRoot = doc.first_node();
    for (rapidxml::xml_node<>* pPluginNode = pRoot->first_node("Plugin"); pPluginNode; pPluginNode = pPluginNode->next_sibling("Plugin"))
    {
        const char* strPluginName = pPluginNode->first_attribute("Name")->value();
        const char* strMain = pPluginNode->first_attribute("Main")->value();

        mPluginNameMap.insert(PluginNameMap::value_type(strPluginName, true));

    }

    rapidxml::xml_node<>* pPluginAppNode = pRoot->first_node("APPID");
    if (!pPluginAppNode)
    {
        NFASSERT(0, "There are no App ID", __FILE__, __FUNCTION__);
        return false;
    }

    const char* strAppID = pPluginAppNode->first_attribute("Name")->value();
    if (!strAppID)
    {
        NFASSERT(0, "There are no App ID", __FILE__, __FUNCTION__);
        return false;
    }

    if (!NF_StrTo(strAppID, mnAppID))
    {
        NFASSERT(0, "App ID Convert Error", __FILE__, __FUNCTION__);
        return false;
    }

    rapidxml::xml_node<>* pPluginConfigPathNode = pRoot->first_node("ConfigPath");
    if (!pPluginConfigPathNode)
    {
        NFASSERT(0, "There are no ConfigPath", __FILE__, __FUNCTION__);
        return false;
    }

    if (NULL == pPluginConfigPathNode->first_attribute("Name"))
    {
        NFASSERT(0, "There are no ConfigPath.Name", __FILE__, __FUNCTION__);
        return false;
    }

    mstrConfigPath = pPluginConfigPathNode->first_attribute("Name")->value();

    return true;
}

void NFCPluginManager::Registered(NFIPlugin* plugin)
{
    std::string strPluginName = plugin->GetPluginName();
    if (!FindPlugin(strPluginName))
    {
        bool bFind = false;
        PluginNameMap::iterator it = mPluginNameMap.begin();
        for (it; it != mPluginNameMap.end(); ++it)
        {
            if (strPluginName == it->first)
            {
                bFind = true;
                break;
            }
        }

        if (bFind)
        {
            mPluginInstanceMap.insert(PluginInstanceMap::value_type(strPluginName, plugin));
            plugin->Install();
        }
    }
}

void NFCPluginManager::UnsRegistered(NFIPlugin* plugin)
{
    PluginInstanceMap::iterator it = mPluginInstanceMap.find(plugin->GetPluginName());
    if (it != mPluginInstanceMap.end())
    {
        it->second->Uninstall();
        delete it->second;
        it->second = NULL;
        mPluginInstanceMap.erase(it);
    }
}

NFIPlugin* NFCPluginManager::FindPlugin(const std::string& strPluginName)
{
    PluginInstanceMap::iterator it = mPluginInstanceMap.find(strPluginName);
    if (it != mPluginInstanceMap.end())
    {
        return it->second;
    }

    return NULL;
}

bool NFCPluginManager::Execute()
{
    mnNowTime = time(NULL);

    bool bRet = true;

    PluginInstanceMap::iterator it = mPluginInstanceMap.begin();
    for (; it != mPluginInstanceMap.end(); ++it)
    {
        bool tembRet = it->second->Execute();
        bRet = bRet && tembRet;
    }

    ExecuteEvent();

    return bRet;
}

void NFCPluginManager::AddModule(const std::string& strModuleName, NFILogicModule* pModule)
{
    if (!FindModule(strModuleName))
    {
        mModuleInstanceMap.insert(ModuleInstanceMap::value_type(strModuleName, pModule));
    }
}

void NFCPluginManager::RemoveModule(const std::string& strModuleName)
{
    ModuleInstanceMap::iterator it = mModuleInstanceMap.find(strModuleName);
    if (it != mModuleInstanceMap.end())
    {
        mModuleInstanceMap.erase(it);
    }
}

NFILogicModule* NFCPluginManager::FindModule(const std::string& strModuleName)
{
    ModuleInstanceMap::iterator it = mModuleInstanceMap.find(strModuleName);
    if (it != mModuleInstanceMap.end())
    {
        return it->second;
    }
    return NULL;
}

bool NFCPluginManager::Init()
{
#ifdef NF_DYNAMIC_PLUGIN
    LoadPlugin();

#if NF_PLATFORM == NF_PLATFORM_WIN || NF_PLATFORM == NF_PLATFORM_LINUX || NF_PLATFORM == NF_PLATFORM_APPLE
    PluginNameMap::iterator it = mPluginNameMap.begin();
    for (it; it != mPluginNameMap.end(); ++it)
    {
        LoadPluginLibrary(it->first);
    }

#endif

#else
    //     PluginNameList::iterator it = mPluginNameList.begin();
    //     for (it; it != mPluginNameList.end(); it++)
    //     {
    //         const std::string& strPluginName = *it;
    //         CREATE_PLUGIN( this, strPluginName );
    //     }

    //     CREATE_PLUGIN(this, NFKernelPlugin)
    //     CREATE_PLUGIN(this, NFEventProcessPlugin)
    //     CREATE_PLUGIN(this, NFConfigPlugin)

#endif

    PluginInstanceMap::iterator itInstance = mPluginInstanceMap.begin();
    for (itInstance; itInstance != mPluginInstanceMap.end(); itInstance++)
    {
        itInstance->second->Init();
    }

    return true;
}

bool NFCPluginManager::AfterInit()
{
    PluginInstanceMap::iterator itAfterInstance = mPluginInstanceMap.begin();
    for (itAfterInstance; itAfterInstance != mPluginInstanceMap.end(); itAfterInstance++)
    {
        itAfterInstance->second->AfterInit();
    }

    return true;
}

bool NFCPluginManager::CheckConfig()
{
    PluginInstanceMap::iterator itCheckInstance = mPluginInstanceMap.begin();
    for (itCheckInstance; itCheckInstance != mPluginInstanceMap.end(); itCheckInstance++)
    {
        itCheckInstance->second->CheckConfig();
    }

    return true;
}

bool NFCPluginManager::BeforeShut()
{
    PluginInstanceMap::iterator itBeforeInstance = mPluginInstanceMap.begin();
    for (itBeforeInstance; itBeforeInstance != mPluginInstanceMap.end(); itBeforeInstance++)
    {
        itBeforeInstance->second->BeforeShut();
    }

    return true;
}

bool NFCPluginManager::Shut()
{

    PluginInstanceMap::iterator itInstance = mPluginInstanceMap.begin();
    for (itInstance; itInstance != mPluginInstanceMap.end(); ++itInstance)
    {
        itInstance->second->Shut();
    }

#ifdef NF_DYNAMIC_PLUGIN

    PluginNameMap::iterator it = mPluginNameMap.begin();
    for (it; it != mPluginNameMap.end(); it++)
    {
        UnLoadPluginLibrary(it->first);
    }

#else

    //     DESTROY_PLUGIN(this, NFConfigPlugin)
    //     DESTROY_PLUGIN(this, NFEventProcessPlugin)
    //     DESTROY_PLUGIN(this, NFKernelPlugin)

#endif
    mPluginInstanceMap.clear();
    mPluginNameMap.clear();
    return true;
}

bool NFCPluginManager::LoadPluginLibrary(const std::string& strPluginDLLName)
{
    PluginLibMap::iterator it = mPluginLibMap.find(strPluginDLLName);
    if (it == mPluginLibMap.end())
    {
        NFCDynLib* pLib = new NFCDynLib(strPluginDLLName);
        bool bLoad = pLib->Load();

        if (bLoad)
        {
            mPluginLibMap.insert(PluginLibMap::value_type(strPluginDLLName, pLib));

            DLL_START_PLUGIN_FUNC pFunc = (DLL_START_PLUGIN_FUNC)pLib->GetSymbol("DllStartPlugin");
            if (!pFunc)
            {
                std::cout << "Find function DllStartPlugin Failed in [" << pLib->GetName() << "]" << std::endl;
                assert(0);
                return false;
            }

            pFunc(this);

            return true;
        }
        else
        {
#if NF_PLATFORM == NF_PLATFORM_LINUX
            char* error = dlerror();
            if (error)
            {
                std::cout << stderr << " Load shared lib[" << pLib->GetName() << "] failed, ErrorNo. = [" << error << "]" << std::endl;
                std::cout << "Load [" << pLib->GetName() << "] failed" << std::endl;
                assert(0);
                return false;
            }
#elif NF_PLATFORM == NF_PLATFORM_WIN
            std::cout << stderr << " Load DLL[" << pLib->GetName() << "] failed, ErrorNo. = [" << GetLastError() << "]" << std::endl;
            std::cout << "Load [" << pLib->GetName() << "] failed" << std::endl;
            assert(0);
            return false;
#endif // NF_PLATFORM
        }
    }

    return false;
}

bool NFCPluginManager::UnLoadPluginLibrary(const std::string& strPluginDLLName)
{
    PluginLibMap::iterator it = mPluginLibMap.find(strPluginDLLName);
    if (it != mPluginLibMap.end())
    {
        NFCDynLib* pLib = it->second;

        DLL_STOP_PLUGIN_FUNC pFunc = (DLL_STOP_PLUGIN_FUNC)pLib->GetSymbol("DllStopPlugin");

        if (pFunc)
        {
            pFunc(this);
        }

        pLib->UnLoad();

        delete pLib;
        pLib = NULL;
        mPluginLibMap.erase(it);

        return true;
    }

    return false;
}

bool NFCPluginManager::ReInitialize()
{
    PluginInstanceMap::iterator itBeforeInstance = mPluginInstanceMap.begin();
    for (itBeforeInstance; itBeforeInstance != mPluginInstanceMap.end(); itBeforeInstance++)
    {
        itBeforeInstance->second->BeforeShut();
    }

    PluginInstanceMap::iterator itShutDownInstance = mPluginInstanceMap.begin();
    for (itShutDownInstance; itShutDownInstance != mPluginInstanceMap.end(); itShutDownInstance++)
    {
        itShutDownInstance->second->Shut();
    }

    PluginInstanceMap::iterator itInstance = mPluginInstanceMap.begin();
    for (itInstance; itInstance != mPluginInstanceMap.end(); itInstance++)
    {
        itInstance->second->Init();
    }

    PluginInstanceMap::iterator itAfterInstance = mPluginInstanceMap.begin();
    for (; itAfterInstance != mPluginInstanceMap.end(); itAfterInstance++)
    {
        itAfterInstance->second->AfterInit();
    }

    PluginInstanceMap::iterator itCheckInstance = mPluginInstanceMap.begin();
    for (itCheckInstance; itCheckInstance != mPluginInstanceMap.end(); itCheckInstance++)
    {
        itCheckInstance->second->CheckConfig();
    }

    return true;
}

void NFCPluginManager::HandlerEx(const NFIActorMessage& message, const Theron::Address from)
{
    //ӵУÿִ֡
    mxQueue.Push(message);
}

bool NFCPluginManager::ExecuteEvent()
{
    NFIActorMessage xMsg;
    bool bRet = false;
    bRet = mxQueue.Pop(xMsg);
    while (bRet)
    {
        if (xMsg.eType == NFIActorMessage::EACTOR_RETURN_EVENT_MSG)
        {
            xMsg.xEndFuncptr->operator()(xMsg.self, xMsg.nFormActor, xMsg.nSubMsgID, xMsg.data);
            m_pActorManager->ReleaseActor(xMsg.nFormActor);
        }

        bRet = mxQueue.Pop(xMsg);
    }

    return true;
}

void NFCPluginManager::AddComponent(const std::string& strComponentName, NFIComponent* pComponent)
{
    if (!FindComponent(strComponentName))
    {
        mComponentInstanceMap.insert(ComponentInstanceMap::value_type(strComponentName, pComponent));
    }

}

void NFCPluginManager::RemoveComponent(const std::string& strComponentName)
{
    ComponentInstanceMap::iterator it = mComponentInstanceMap.find(strComponentName);
    if (it != mComponentInstanceMap.end())
    {
        mComponentInstanceMap.erase(it);
    }
}

NFIComponent* NFCPluginManager::FindComponent(const std::string& strComponentName)
{
    ComponentInstanceMap::iterator it = mComponentInstanceMap.find(strComponentName);
    if (it != mComponentInstanceMap.end())
    {
        return it->second;
    }
    return NULL;
}
<commit_msg>fix some bugs in AsyMysql<commit_after>// -------------------------------------------------------------------------
//    @FileName      :    NFCPluginManager.cpp
//    @Author           :    LvSheng.Huang
//    @Date             :    2012-12-15
//    @Module           :    NFCPluginManager
//
// -------------------------------------------------------------------------

#include "NFCPluginManager.h"
#include "NFComm/RapidXML/rapidxml.hpp"
#include "NFComm/RapidXML/rapidxml_iterators.hpp"
#include "NFComm/RapidXML/rapidxml_print.hpp"
#include "NFComm/RapidXML/rapidxml_utils.hpp"
#include "NFComm/NFPluginModule/NFIPlugin.h"
#include "NFComm/NFPluginModule/NFIActorDataModule.h"
#include "NFComm/NFPluginModule/NFPlatform.h"

#pragma comment( lib, "ws2_32.lib" )

#ifdef NF_DEBUG_MODE

#if NF_PLATFORM == NF_PLATFORM_WIN
#pragma comment( lib, "Theron_d.lib" )
#elif NF_PLATFORM == NF_PLATFORM_LINUX || NF_PLATFORM == NF_PLATFORM_ANDROID
#pragma comment( lib, "Theron_d.a" )
#elif NF_PLATFORM == NF_PLATFORM_APPLE || NF_PLATFORM == NF_PLATFORM_APPLE_IOS
#pragma comment( lib, "Theron_d.a" )
#endif

#else

#if NF_PLATFORM == NF_PLATFORM_WIN
#pragma comment( lib, "Theron.lib" )
#elif NF_PLATFORM == NF_PLATFORM_LINUX || NF_PLATFORM == NF_PLATFORM_ANDROID
#pragma comment( lib, "Theron.a" )
#elif NF_PLATFORM == NF_PLATFORM_APPLE || NF_PLATFORM == NF_PLATFORM_APPLE_IOS
#pragma comment( lib, "Theron.a" )
#endif

#endif

bool NFCPluginManager::LoadPlugin()
{
    rapidxml::file<> fdoc("Plugin.xml");
    rapidxml::xml_document<>  doc;
    doc.parse<0>(fdoc.data());

    rapidxml::xml_node<>* pRoot = doc.first_node();
    for (rapidxml::xml_node<>* pPluginNode = pRoot->first_node("Plugin"); pPluginNode; pPluginNode = pPluginNode->next_sibling("Plugin"))
    {
        const char* strPluginName = pPluginNode->first_attribute("Name")->value();
        const char* strMain = pPluginNode->first_attribute("Main")->value();

        mPluginNameMap.insert(PluginNameMap::value_type(strPluginName, true));

    }

    rapidxml::xml_node<>* pPluginAppNode = pRoot->first_node("APPID");
    if (!pPluginAppNode)
    {
        NFASSERT(0, "There are no App ID", __FILE__, __FUNCTION__);
        return false;
    }

    const char* strAppID = pPluginAppNode->first_attribute("Name")->value();
    if (!strAppID)
    {
        NFASSERT(0, "There are no App ID", __FILE__, __FUNCTION__);
        return false;
    }

    if (!NF_StrTo(strAppID, mnAppID))
    {
        NFASSERT(0, "App ID Convert Error", __FILE__, __FUNCTION__);
        return false;
    }

    rapidxml::xml_node<>* pPluginConfigPathNode = pRoot->first_node("ConfigPath");
    if (!pPluginConfigPathNode)
    {
        NFASSERT(0, "There are no ConfigPath", __FILE__, __FUNCTION__);
        return false;
    }

    if (NULL == pPluginConfigPathNode->first_attribute("Name"))
    {
        NFASSERT(0, "There are no ConfigPath.Name", __FILE__, __FUNCTION__);
        return false;
    }

    mstrConfigPath = pPluginConfigPathNode->first_attribute("Name")->value();

    return true;
}

void NFCPluginManager::Registered(NFIPlugin* plugin)
{
    std::string strPluginName = plugin->GetPluginName();
    if (!FindPlugin(strPluginName))
    {
        bool bFind = false;
        PluginNameMap::iterator it = mPluginNameMap.begin();
        for (it; it != mPluginNameMap.end(); ++it)
        {
            if (strPluginName == it->first)
            {
                bFind = true;
                break;
            }
        }

        if (bFind)
        {
            mPluginInstanceMap.insert(PluginInstanceMap::value_type(strPluginName, plugin));
            plugin->Install();
        }
    }
}

void NFCPluginManager::UnsRegistered(NFIPlugin* plugin)
{
    PluginInstanceMap::iterator it = mPluginInstanceMap.find(plugin->GetPluginName());
    if (it != mPluginInstanceMap.end())
    {
        it->second->Uninstall();
        delete it->second;
        it->second = NULL;
        mPluginInstanceMap.erase(it);
    }
}

NFIPlugin* NFCPluginManager::FindPlugin(const std::string& strPluginName)
{
    PluginInstanceMap::iterator it = mPluginInstanceMap.find(strPluginName);
    if (it != mPluginInstanceMap.end())
    {
        return it->second;
    }

    return NULL;
}

bool NFCPluginManager::Execute()
{
    mnNowTime = time(NULL);

    bool bRet = true;

    PluginInstanceMap::iterator it = mPluginInstanceMap.begin();
    for (; it != mPluginInstanceMap.end(); ++it)
    {
        bool tembRet = it->second->Execute();
        bRet = bRet && tembRet;
    }

    ExecuteEvent();

    return bRet;
}

void NFCPluginManager::AddModule(const std::string& strModuleName, NFILogicModule* pModule)
{
    if (!FindModule(strModuleName))
    {
        mModuleInstanceMap.insert(ModuleInstanceMap::value_type(strModuleName, pModule));
    }
}

void NFCPluginManager::RemoveModule(const std::string& strModuleName)
{
    ModuleInstanceMap::iterator it = mModuleInstanceMap.find(strModuleName);
    if (it != mModuleInstanceMap.end())
    {
        mModuleInstanceMap.erase(it);
    }
}

NFILogicModule* NFCPluginManager::FindModule(const std::string& strModuleName)
{
    ModuleInstanceMap::iterator it = mModuleInstanceMap.find(strModuleName);
    if (it != mModuleInstanceMap.end())
    {
        return it->second;
    }
    return NULL;
}

bool NFCPluginManager::Init()
{
#ifdef NF_DYNAMIC_PLUGIN
    LoadPlugin();

#if NF_PLATFORM == NF_PLATFORM_WIN || NF_PLATFORM == NF_PLATFORM_LINUX || NF_PLATFORM == NF_PLATFORM_APPLE
    PluginNameMap::iterator it = mPluginNameMap.begin();
    for (it; it != mPluginNameMap.end(); ++it)
    {
        LoadPluginLibrary(it->first);
    }

#endif

#else
    //     PluginNameList::iterator it = mPluginNameList.begin();
    //     for (it; it != mPluginNameList.end(); it++)
    //     {
    //         const std::string& strPluginName = *it;
    //         CREATE_PLUGIN( this, strPluginName );
    //     }

    //     CREATE_PLUGIN(this, NFKernelPlugin)
    //     CREATE_PLUGIN(this, NFEventProcessPlugin)
    //     CREATE_PLUGIN(this, NFConfigPlugin)

#endif

    PluginInstanceMap::iterator itInstance = mPluginInstanceMap.begin();
    for (itInstance; itInstance != mPluginInstanceMap.end(); itInstance++)
    {
        itInstance->second->Init();
    }

    return true;
}

bool NFCPluginManager::AfterInit()
{
    PluginInstanceMap::iterator itAfterInstance = mPluginInstanceMap.begin();
    for (itAfterInstance; itAfterInstance != mPluginInstanceMap.end(); itAfterInstance++)
    {
        itAfterInstance->second->AfterInit();
    }

    return true;
}

bool NFCPluginManager::CheckConfig()
{
    PluginInstanceMap::iterator itCheckInstance = mPluginInstanceMap.begin();
    for (itCheckInstance; itCheckInstance != mPluginInstanceMap.end(); itCheckInstance++)
    {
        itCheckInstance->second->CheckConfig();
    }

    return true;
}

bool NFCPluginManager::BeforeShut()
{
    PluginInstanceMap::iterator itBeforeInstance = mPluginInstanceMap.begin();
    for (itBeforeInstance; itBeforeInstance != mPluginInstanceMap.end(); itBeforeInstance++)
    {
        itBeforeInstance->second->BeforeShut();
    }

    return true;
}

bool NFCPluginManager::Shut()
{

    PluginInstanceMap::iterator itInstance = mPluginInstanceMap.begin();
    for (itInstance; itInstance != mPluginInstanceMap.end(); ++itInstance)
    {
        itInstance->second->Shut();
    }

#ifdef NF_DYNAMIC_PLUGIN

    PluginNameMap::iterator it = mPluginNameMap.begin();
    for (it; it != mPluginNameMap.end(); it++)
    {
        UnLoadPluginLibrary(it->first);
    }

#else

    //     DESTROY_PLUGIN(this, NFConfigPlugin)
    //     DESTROY_PLUGIN(this, NFEventProcessPlugin)
    //     DESTROY_PLUGIN(this, NFKernelPlugin)

#endif
    mPluginInstanceMap.clear();
    mPluginNameMap.clear();
    return true;
}

bool NFCPluginManager::LoadPluginLibrary(const std::string& strPluginDLLName)
{
    PluginLibMap::iterator it = mPluginLibMap.find(strPluginDLLName);
    if (it == mPluginLibMap.end())
    {
        NFCDynLib* pLib = new NFCDynLib(strPluginDLLName);
        bool bLoad = pLib->Load();

        if (bLoad)
        {
            mPluginLibMap.insert(PluginLibMap::value_type(strPluginDLLName, pLib));

            DLL_START_PLUGIN_FUNC pFunc = (DLL_START_PLUGIN_FUNC)pLib->GetSymbol("DllStartPlugin");
            if (!pFunc)
            {
                std::cout << "Find function DllStartPlugin Failed in [" << pLib->GetName() << "]" << std::endl;
                assert(0);
                return false;
            }

            pFunc(this);

            return true;
        }
        else
        {
#if NF_PLATFORM == NF_PLATFORM_LINUX
            char* error = dlerror();
            if (error)
            {
                std::cout << stderr << " Load shared lib[" << pLib->GetName() << "] failed, ErrorNo. = [" << error << "]" << std::endl;
                std::cout << "Load [" << pLib->GetName() << "] failed" << std::endl;
                assert(0);
                return false;
            }
#elif NF_PLATFORM == NF_PLATFORM_WIN
            std::cout << stderr << " Load DLL[" << pLib->GetName() << "] failed, ErrorNo. = [" << GetLastError() << "]" << std::endl;
            std::cout << "Load [" << pLib->GetName() << "] failed" << std::endl;
            assert(0);
            return false;
#endif // NF_PLATFORM
        }
    }

    return false;
}

bool NFCPluginManager::UnLoadPluginLibrary(const std::string& strPluginDLLName)
{
    PluginLibMap::iterator it = mPluginLibMap.find(strPluginDLLName);
    if (it != mPluginLibMap.end())
    {
        NFCDynLib* pLib = it->second;

        DLL_STOP_PLUGIN_FUNC pFunc = (DLL_STOP_PLUGIN_FUNC)pLib->GetSymbol("DllStopPlugin");

        if (pFunc)
        {
            pFunc(this);
        }

        pLib->UnLoad();

        delete pLib;
        pLib = NULL;
        mPluginLibMap.erase(it);

        return true;
    }

    return false;
}

bool NFCPluginManager::ReInitialize()
{
    PluginInstanceMap::iterator itBeforeInstance = mPluginInstanceMap.begin();
    for (itBeforeInstance; itBeforeInstance != mPluginInstanceMap.end(); itBeforeInstance++)
    {
        itBeforeInstance->second->BeforeShut();
    }

    PluginInstanceMap::iterator itShutDownInstance = mPluginInstanceMap.begin();
    for (itShutDownInstance; itShutDownInstance != mPluginInstanceMap.end(); itShutDownInstance++)
    {
        itShutDownInstance->second->Shut();
    }

    PluginInstanceMap::iterator itInstance = mPluginInstanceMap.begin();
    for (itInstance; itInstance != mPluginInstanceMap.end(); itInstance++)
    {
        itInstance->second->Init();
    }

    PluginInstanceMap::iterator itAfterInstance = mPluginInstanceMap.begin();
    for (; itAfterInstance != mPluginInstanceMap.end(); itAfterInstance++)
    {
        itAfterInstance->second->AfterInit();
    }

    PluginInstanceMap::iterator itCheckInstance = mPluginInstanceMap.begin();
    for (itCheckInstance; itCheckInstance != mPluginInstanceMap.end(); itCheckInstance++)
    {
        itCheckInstance->second->CheckConfig();
    }

    return true;
}

void NFCPluginManager::HandlerEx(const NFIActorMessage& message, const Theron::Address from)
{
    //ӵУÿִ֡
    mxQueue.Push(message);
}

bool NFCPluginManager::ExecuteEvent()
{
    NFIActorMessage xMsg;
    bool bRet = false;
    bRet = mxQueue.Pop(xMsg);
    while (bRet)
    {
        if (xMsg.eType == NFIActorMessage::EACTOR_RETURN_EVENT_MSG)
        {
            xMsg.xEndFuncptr->operator()(xMsg.self, xMsg.nFormActor, xMsg.nSubMsgID, xMsg.data);
            //Actor can be reused in ActorPool mode, so we don't release it.
            //m_pActorManager->ReleaseActor(xMsg.nFormActor);
        }

        bRet = mxQueue.Pop(xMsg);
    }

    return true;
}

void NFCPluginManager::AddComponent(const std::string& strComponentName, NFIComponent* pComponent)
{
    if (!FindComponent(strComponentName))
    {
        mComponentInstanceMap.insert(ComponentInstanceMap::value_type(strComponentName, pComponent));
    }

}

void NFCPluginManager::RemoveComponent(const std::string& strComponentName)
{
    ComponentInstanceMap::iterator it = mComponentInstanceMap.find(strComponentName);
    if (it != mComponentInstanceMap.end())
    {
        mComponentInstanceMap.erase(it);
    }
}

NFIComponent* NFCPluginManager::FindComponent(const std::string& strComponentName)
{
    ComponentInstanceMap::iterator it = mComponentInstanceMap.find(strComponentName);
    if (it != mComponentInstanceMap.end())
    {
        return it->second;
    }
    return NULL;
}
<|endoftext|>


<commit_before>/*
 * String hash map.
 *
 * author: Max Kellermann <mk@cm4all.com>
 */

#ifndef BENG_PROXY_STRMAP_HXX
#define BENG_PROXY_STRMAP_HXX

#include <inline/compiler.h>

#include <boost/intrusive/set.hpp>

struct pool;

struct strmap_pair {
    const char *key, *value;

    constexpr strmap_pair(const char *_key, const char *_value)
        :key(_key), value(_value) {}
};

struct strmap {
    struct Item : strmap_pair {
        typedef boost::intrusive::set_member_hook<boost::intrusive::link_mode<boost::intrusive::normal_link>> Hook;
        Hook hook;

        Item(const char *_key, const char *_value)
            :strmap_pair(_key, _value) {}

        class Compare {
            gcc_pure
            bool Less(const char *a, const char *b) const;

        public:
            gcc_pure
            bool operator()(const char *a, const Item &b) const {
                return Less(a, b.key);
            }

            gcc_pure
            bool operator()(const Item &a, const char *b) const {
                return Less(a.key, b);
            }

            gcc_pure
            bool operator()(const Item &a, const Item &b) const {
                return Less(a.key, b.key);
            }
        };
    };

    struct pool &pool;

    typedef boost::intrusive::multiset<Item,
                                       boost::intrusive::member_hook<Item, Item::Hook, &Item::hook>,
                                       boost::intrusive::compare<Item::Compare>,
                                       boost::intrusive::constant_time_size<false>> Map;

    typedef Map::const_iterator const_iterator;

    Map map;

    explicit strmap(struct pool &_pool):pool(_pool) {}

    strmap(struct pool &_pool, const strmap &src);

    strmap(const strmap &) = delete;

    const_iterator begin() const {
        return map.begin();
    }

    const_iterator end() const {
        return map.end();
    }

    void Add(const char *key, const char *value);
    const char *Set(const char *key, const char *value);
    const char *Remove(const char *key);

    gcc_pure
    const char *Get(const char *key) const;

    gcc_pure
    std::pair<const_iterator, const_iterator> EqualRange(const char *key) const;
};

struct strmap *gcc_malloc
strmap_new(struct pool *pool);

struct strmap *gcc_malloc
strmap_dup(struct pool *pool, struct strmap *src);

static inline const char *
strmap_get(const struct strmap *map, const char *key)
{
    return map->Get(key);
}

/**
 * This variation of strmap::Remove() allows the caller to pass
 * map=nullptr.
 */
static inline const char *
strmap_remove_checked(struct strmap *map, const char *key)
{
    return map != nullptr
        ? map->Remove(key)
        : nullptr;
}

/**
 * This variation of strmap_get() allows the caller to pass map=nullptr.
 */
gcc_pure
static inline const char *
strmap_get_checked(const struct strmap *map, const char *key)
{
    return map != nullptr
        ? strmap_get(map, key)
        : nullptr;
}

#endif
<commit_msg>strmap: hide struct strmap_pair<commit_after>/*
 * String hash map.
 *
 * author: Max Kellermann <mk@cm4all.com>
 */

#ifndef BENG_PROXY_STRMAP_HXX
#define BENG_PROXY_STRMAP_HXX

#include <inline/compiler.h>

#include <boost/intrusive/set.hpp>

struct pool;

struct strmap {
    struct Item {
        typedef boost::intrusive::set_member_hook<boost::intrusive::link_mode<boost::intrusive::normal_link>> Hook;
        Hook hook;

        const char *key, *value;

        Item(const char *_key, const char *_value)
            :key(_key), value(_value) {}

        class Compare {
            gcc_pure
            bool Less(const char *a, const char *b) const;

        public:
            gcc_pure
            bool operator()(const char *a, const Item &b) const {
                return Less(a, b.key);
            }

            gcc_pure
            bool operator()(const Item &a, const char *b) const {
                return Less(a.key, b);
            }

            gcc_pure
            bool operator()(const Item &a, const Item &b) const {
                return Less(a.key, b.key);
            }
        };
    };

    struct pool &pool;

    typedef boost::intrusive::multiset<Item,
                                       boost::intrusive::member_hook<Item, Item::Hook, &Item::hook>,
                                       boost::intrusive::compare<Item::Compare>,
                                       boost::intrusive::constant_time_size<false>> Map;

    typedef Map::const_iterator const_iterator;

    Map map;

    explicit strmap(struct pool &_pool):pool(_pool) {}

    strmap(struct pool &_pool, const strmap &src);

    strmap(const strmap &) = delete;

    const_iterator begin() const {
        return map.begin();
    }

    const_iterator end() const {
        return map.end();
    }

    void Add(const char *key, const char *value);
    const char *Set(const char *key, const char *value);
    const char *Remove(const char *key);

    gcc_pure
    const char *Get(const char *key) const;

    gcc_pure
    std::pair<const_iterator, const_iterator> EqualRange(const char *key) const;
};

struct strmap *gcc_malloc
strmap_new(struct pool *pool);

struct strmap *gcc_malloc
strmap_dup(struct pool *pool, struct strmap *src);

static inline const char *
strmap_get(const struct strmap *map, const char *key)
{
    return map->Get(key);
}

/**
 * This variation of strmap::Remove() allows the caller to pass
 * map=nullptr.
 */
static inline const char *
strmap_remove_checked(struct strmap *map, const char *key)
{
    return map != nullptr
        ? map->Remove(key)
        : nullptr;
}

/**
 * This variation of strmap_get() allows the caller to pass map=nullptr.
 */
gcc_pure
static inline const char *
strmap_get_checked(const struct strmap *map, const char *key)
{
    return map != nullptr
        ? strmap_get(map, key)
        : nullptr;
}

#endif
<|endoftext|>


<commit_before>/**
 * Created by Jian Chen
 * @since  2016.01.29
 * @author Jian Chen <admin@chensoft.com>
 * @link   http://chensoft.com
 */
#include <chen/sys/fs.hpp>
#include <chen/base/str.hpp>
#include <fstream>
#include <cstdlib>

using namespace chen;

// -----------------------------------------------------------------------------
// path
std::string fs::realpath(const std::string &path)
{
    char buf[PATH_MAX] = {0};
    ::realpath(path.c_str(), buf);

    std::string ret(buf);
    return fs::isExist(ret) ? ret : "";
}

std::string fs::absolute(const std::string &path)
{
    if (fs::isRelative(path))
        return fs::current() + fs::separator() + fs::normalize(path);
    else
        return fs::normalize(path);
}

std::string fs::normalize(const std::string &path)
{
    if (path.empty())
        return "";

    auto sep = fs::separator();
    auto abs = (path[0] == sep);

    std::size_t ptr = 0;  // current segment cursor
    std::size_t len = 0;  // current segment length

    std::vector<std::pair<std::size_t, std::size_t>> store;  // segments cache

    for (std::size_t i = 0, l = path.size(); (i < l) || len; ++i)
    {
        if ((i == l) || (path[i] == sep))
        {
            if (len > 0)
            {
                // store a segment
                if (str::equal(&path[ptr], len, "..", 2))
                {
                    if (!store.empty() && !str::equal(&path[store.back().first], store.back().second, "..", 2))
                        store.pop_back();
                    else
                        store.push_back(std::make_pair(ptr, len));
                }
                else if (!str::equal(&path[ptr], len, ".", 1))
                {
                    store.push_back(std::make_pair(ptr, len));
                }

                ptr = len = 0;
            }
        }
        else
        {
            if (!len)
            {
                ptr = i;
                len = 1;
            }
            else
            {
                ++len;
            }
        }
    }

    // concat
    std::string ret(abs ? "/" : "");

    for (std::size_t i = 0, l = store.size(); i < l; ++i)
    {
        auto &pair = store[i];
        ret.append(&path[pair.first], pair.second);

        if (i < l - 1)
            ret.append(1, sep);
    }

    return ret;
}

std::string fs::dirname(const std::string &path)
{
    if (path.empty())
        return "";

    auto sep = fs::separator();
    auto beg = path.rbegin();
    auto end = path.rend();
    auto idx = beg;

    auto flag = false;

    for (; idx != end; ++idx)
    {
        if (*idx == sep)
        {
            auto next = idx + 1;

            if (flag && (*next != sep))
            {
                ++idx;
                break;
            }
        }
        else if (!flag)
        {
            flag = true;
        }
    }

    if (flag)
    {
        if (idx != end)
        {
            return path.substr(0, static_cast<std::size_t>(end - idx));
        }
        else
        {
            auto first = path[0];
            return (first == sep) ? "/" : ".";  // using root directory or current directory
        }
    }
    else
    {
        return "/";  // all chars are '/'
    }
}

std::string fs::basename(const std::string &path)
{
    auto sep = fs::separator();
    auto beg = path.rbegin();
    auto end = path.rend();

    auto flag_a = end;  // before
    auto flag_b = end;  // after

    for (auto idx = beg; idx != end; ++idx)
    {
        if (*idx == sep)
        {
            if (flag_b != end)
            {
                flag_a = idx;
                break;
            }
        }
        else if (flag_b == end)
        {
            flag_b = idx;
        }
    }

    if (flag_b != end)
        return path.substr(static_cast<std::size_t>(end - flag_a), static_cast<std::size_t>(flag_a - flag_b));
    else
        return "";
}

std::string fs::extname(const std::string &path, std::size_t dots)
{
    if (!dots)
        return "";

    auto sep = fs::separator();
    auto beg = path.rbegin();
    auto end = path.rend();
    auto idx = beg;
    auto cur = beg;
    auto num = 0;

    for (; idx != end; ++idx)
    {
        if (*idx == sep)
        {
            break;
        }
        else if (*idx == '.')
        {
            cur = idx + 1;

            if (++num == dots)
                break;
        }
    }

    return num ? path.substr(static_cast<std::size_t>(end - cur), static_cast<std::size_t>(cur - beg)) : "";
}

// exist
bool fs::isAbsolute(const std::string &path)
{
    auto sep = fs::separator();
    return !path.empty() && (path[0] == sep);
}

bool fs::isRelative(const std::string &path)
{
    return !fs::isAbsolute(path);
}

// copy
bool fs::copy(const std::string &path_old, const std::string &path_new)
{
    if (fs::isFile(path_old))
    {
        auto folder = fs::dirname(path_new);
        if (folder.empty())
            return false;

        if (!fs::create(folder))
            return false;

        std::ifstream in(path_old, std::ios_base::binary);
        if (!in)
            return false;

        std::ofstream out(path_new, std::ios_base::binary);
        if (!out)
            return false;

        out << in.rdbuf();
        out.close();

        return true;
    }
    else if (fs::isDir(path_old, true))
    {
        if (!fs::create(path_new))
            return false;

        auto size = path_old.size();
        auto ret  = true;

        fs::visit(path_old, [size, &ret, path_new] (const std::string &name) -> bool {
            auto sub = name.substr(size, name.size() - size);

            if (fs::isFile(name))
                ret = fs::copy(name, path_new + sub);
            else
                ret = fs::create(path_new + sub, 0, false);

            // exit if occur an error
            return ret;
        });

        return ret;
    }
    else
    {
        return false;
    }
}

// visit
std::vector<std::string> fs::collect(const std::string &directory, bool recursive)
{
    std::vector<std::string> store;

    fs::visit(directory, [&store] (const std::string &path) -> bool {
        store.push_back(path);
        return true;
    }, recursive);

    return store;
}

// count
std::size_t fs::count(const std::string &directory,
                        bool recursive,
                        bool contain_file,
                        bool contain_dir)
{
    if (!contain_file && !contain_dir)
        return 0;

    std::size_t num = 0;

    fs::visit(directory, [&] (const std::string &path) -> bool {
        if ((contain_file && contain_dir) ||
            (contain_file && fs::isFile(path)) ||
            (contain_dir && fs::isDir(path)))
        {
            ++num;
        }

        return true;
    }, recursive);

    return num;
}<commit_msg>fs: fix compile on Ubuntu u error<commit_after>/**
 * Created by Jian Chen
 * @since  2016.01.29
 * @author Jian Chen <admin@chensoft.com>
 * @link   http://chensoft.com
 */
#include <chen/sys/fs.hpp>
#include <chen/base/str.hpp>
#include <fstream>
#include <cstdlib>
#include <climits>

using namespace chen;

// -----------------------------------------------------------------------------
// path
std::string fs::realpath(const std::string &path)
{
    char buf[PATH_MAX] = {0};
    ::realpath(path.c_str(), buf);

    std::string ret(buf);
    return fs::isExist(ret) ? ret : "";
}

std::string fs::absolute(const std::string &path)
{
    if (fs::isRelative(path))
        return fs::current() + fs::separator() + fs::normalize(path);
    else
        return fs::normalize(path);
}

std::string fs::normalize(const std::string &path)
{
    if (path.empty())
        return "";

    auto sep = fs::separator();
    auto abs = (path[0] == sep);

    std::size_t ptr = 0;  // current segment cursor
    std::size_t len = 0;  // current segment length

    std::vector<std::pair<std::size_t, std::size_t>> store;  // segments cache

    for (std::size_t i = 0, l = path.size(); (i < l) || len; ++i)
    {
        if ((i == l) || (path[i] == sep))
        {
            if (len > 0)
            {
                // store a segment
                if (str::equal(&path[ptr], len, "..", 2))
                {
                    if (!store.empty() && !str::equal(&path[store.back().first], store.back().second, "..", 2))
                        store.pop_back();
                    else
                        store.push_back(std::make_pair(ptr, len));
                }
                else if (!str::equal(&path[ptr], len, ".", 1))
                {
                    store.push_back(std::make_pair(ptr, len));
                }

                ptr = len = 0;
            }
        }
        else
        {
            if (!len)
            {
                ptr = i;
                len = 1;
            }
            else
            {
                ++len;
            }
        }
    }

    // concat
    std::string ret(abs ? "/" : "");

    for (std::size_t i = 0, l = store.size(); i < l; ++i)
    {
        auto &pair = store[i];
        ret.append(&path[pair.first], pair.second);

        if (i < l - 1)
            ret.append(1, sep);
    }

    return ret;
}

std::string fs::dirname(const std::string &path)
{
    if (path.empty())
        return "";

    auto sep = fs::separator();
    auto beg = path.rbegin();
    auto end = path.rend();
    auto idx = beg;

    auto flag = false;

    for (; idx != end; ++idx)
    {
        if (*idx == sep)
        {
            auto next = idx + 1;

            if (flag && (*next != sep))
            {
                ++idx;
                break;
            }
        }
        else if (!flag)
        {
            flag = true;
        }
    }

    if (flag)
    {
        if (idx != end)
        {
            return path.substr(0, static_cast<std::size_t>(end - idx));
        }
        else
        {
            auto first = path[0];
            return (first == sep) ? "/" : ".";  // using root directory or current directory
        }
    }
    else
    {
        return "/";  // all chars are '/'
    }
}

std::string fs::basename(const std::string &path)
{
    auto sep = fs::separator();
    auto beg = path.rbegin();
    auto end = path.rend();

    auto flag_a = end;  // before
    auto flag_b = end;  // after

    for (auto idx = beg; idx != end; ++idx)
    {
        if (*idx == sep)
        {
            if (flag_b != end)
            {
                flag_a = idx;
                break;
            }
        }
        else if (flag_b == end)
        {
            flag_b = idx;
        }
    }

    if (flag_b != end)
        return path.substr(static_cast<std::size_t>(end - flag_a), static_cast<std::size_t>(flag_a - flag_b));
    else
        return "";
}

std::string fs::extname(const std::string &path, std::size_t dots)
{
    if (!dots)
        return "";

    auto sep = fs::separator();
    auto beg = path.rbegin();
    auto end = path.rend();
    auto idx = beg;
    auto cur = beg;
    auto num = 0;

    for (; idx != end; ++idx)
    {
        if (*idx == sep)
        {
            break;
        }
        else if (*idx == '.')
        {
            cur = idx + 1;

            if (++num == dots)
                break;
        }
    }

    return num ? path.substr(static_cast<std::size_t>(end - cur), static_cast<std::size_t>(cur - beg)) : "";
}

// exist
bool fs::isAbsolute(const std::string &path)
{
    auto sep = fs::separator();
    return !path.empty() && (path[0] == sep);
}

bool fs::isRelative(const std::string &path)
{
    return !fs::isAbsolute(path);
}

// copy
bool fs::copy(const std::string &path_old, const std::string &path_new)
{
    if (fs::isFile(path_old))
    {
        auto folder = fs::dirname(path_new);
        if (folder.empty())
            return false;

        if (!fs::create(folder))
            return false;

        std::ifstream in(path_old, std::ios_base::binary);
        if (!in)
            return false;

        std::ofstream out(path_new, std::ios_base::binary);
        if (!out)
            return false;

        out << in.rdbuf();
        out.close();

        return true;
    }
    else if (fs::isDir(path_old, true))
    {
        if (!fs::create(path_new))
            return false;

        auto size = path_old.size();
        auto ret  = true;

        fs::visit(path_old, [size, &ret, path_new] (const std::string &name) -> bool {
            auto sub = name.substr(size, name.size() - size);

            if (fs::isFile(name))
                ret = fs::copy(name, path_new + sub);
            else
                ret = fs::create(path_new + sub, 0, false);

            // exit if occur an error
            return ret;
        });

        return ret;
    }
    else
    {
        return false;
    }
}

// visit
std::vector<std::string> fs::collect(const std::string &directory, bool recursive)
{
    std::vector<std::string> store;

    fs::visit(directory, [&store] (const std::string &path) -> bool {
        store.push_back(path);
        return true;
    }, recursive);

    return store;
}

// count
std::size_t fs::count(const std::string &directory,
                        bool recursive,
                        bool contain_file,
                        bool contain_dir)
{
    if (!contain_file && !contain_dir)
        return 0;

    std::size_t num = 0;

    fs::visit(directory, [&] (const std::string &path) -> bool {
        if ((contain_file && contain_dir) ||
            (contain_file && fs::isFile(path)) ||
            (contain_dir && fs::isDir(path)))
        {
            ++num;
        }

        return true;
    }, recursive);

    return num;
}<|endoftext|>


<commit_before>#include <algorithm>
#include <cassert>
#include "system.h"
#include "errors.h"
#include "utils.h"

//#include <iostream>
//using namespace std;

const System::MemoryInstance System::MemoryInstance::null(NULL, 0, 0);

int System::installMemory(MemoryModule &mod, SizeType offset, SizeType size) {
    int status = ERR_SUCCESS;

    // NB: if(size <= 0 || /* overflow */offset + size < offset) {
    if(offset + size <= offset) {
        status = ERR_BADRANGE;
    } else {
        MemoryInstance overlap = resolveAtMost(offset + size - 1);
        if(overlap) {
            SizeType overlapEnd = overlap.offset + overlap.length - 1;
            if(overlapEnd >= offset) {
                status = ERR_CONFLICT;
            }
        }
    }

    if(status == ERR_SUCCESS) {
        mem.emplace(offset,  MemoryInstance(&mod, offset, size));
    }
    return status;
}

int System::removeMemory(SizeType offset) {
    MemMap::size_type erased = mem.erase(offset);
    assert(erased <= 1);
    int status = erased ? ERR_SUCCESS : ERR_BADRANGE;
    return status;
}

int System::bindPort(PortSocket &sock, PortType port) {
    throw "Not Implemented";
}

int System::releasePort(PortType port) {
    throw "Not Implemented";
}

int System::readMemory(SizeType offset, SizeType len, void *data) const {
    return memoryLoop(offset, len, data, false);
}

int System::writeMemory(SizeType offset, SizeType len, const void *data) const {
    return memoryLoop(offset, len, data, true);
}

int System::readPort(PortType port, SizeType len, void *data) const {
    throw "Not Implemented";
}

int System::writePort(PortType port, SizeType len, const void *data) const {
    throw "Not Implemented";
}

System::MemoryInstance System::resolveAtMost(SizeType address) const {
    MemoryInstance ret = MemoryInstance::null;
    auto iterator = mem.lower_bound(address);
    if(iterator->second.offset == address) {
        ret = iterator->second;
    } else {
        if(iterator != mem.cbegin()) {
            iterator--;
            ret = iterator->second;
        }
    }
    if(ret.offset > address) {
        ret = MemoryInstance::null;
    }
    return ret;
}

int System::memoryLoop(SizeType offset, SizeType len, const void *data, bool write) const {
    int status = ERR_SUCCESS;
    while(len > 0) {
        MemoryInstance src = resolveAtMost(offset);
        if(!src) {
            status = ERR_BADRANGE;
        } else {
            SizeType srcOff = offset - src.offset;
            //No memory module covers the requested range
            if (srcOff >= src.length) {
                status = ERR_BADRANGE;
            }
            else {
                SizeType srcLen = std::min(src.length - srcOff, len);
                if(write) {
                    status = src.mod->writeMemory(srcOff, srcLen, data);
                } else {
                    status = src.mod->readMemory(srcOff, srcLen, /* HACK */(void*)(data));
                }
                len -= srcLen;
                offset += srcLen;
                data = advancePtr(data, srcLen);
            }
        }
        if(status != ERR_SUCCESS) {
            break;
        }
    }
    return status;
}<commit_msg>Remove debug assert<commit_after>#include <algorithm>
#include <cassert>
#include "system.h"
#include "errors.h"
#include "utils.h"

//#include <iostream>
//using namespace std;

const System::MemoryInstance System::MemoryInstance::null(NULL, 0, 0);

int System::installMemory(MemoryModule &mod, SizeType offset, SizeType size) {
    int status = ERR_SUCCESS;

    // NB: if(size <= 0 || /* overflow */offset + size < offset) {
    if(offset + size <= offset) {
        status = ERR_BADRANGE;
    } else {
        MemoryInstance overlap = resolveAtMost(offset + size - 1);
        if(overlap) {
            SizeType overlapEnd = overlap.offset + overlap.length - 1;
            if(overlapEnd >= offset) {
                status = ERR_CONFLICT;
            }
        }
    }

    if(status == ERR_SUCCESS) {
        mem.emplace(offset,  MemoryInstance(&mod, offset, size));
    }
    return status;
}

int System::removeMemory(SizeType offset) {
    MemMap::size_type erased = mem.erase(offset);
    int status = erased ? ERR_SUCCESS : ERR_BADRANGE;
    return status;
}

int System::bindPort(PortSocket &sock, PortType port) {
    throw "Not Implemented";
}

int System::releasePort(PortType port) {
    throw "Not Implemented";
}

int System::readMemory(SizeType offset, SizeType len, void *data) const {
    return memoryLoop(offset, len, data, false);
}

int System::writeMemory(SizeType offset, SizeType len, const void *data) const {
    return memoryLoop(offset, len, data, true);
}

int System::readPort(PortType port, SizeType len, void *data) const {
    throw "Not Implemented";
}

int System::writePort(PortType port, SizeType len, const void *data) const {
    throw "Not Implemented";
}

System::MemoryInstance System::resolveAtMost(SizeType address) const {
    MemoryInstance ret = MemoryInstance::null;
    auto iterator = mem.lower_bound(address);
    if(iterator->second.offset == address) {
        ret = iterator->second;
    } else {
        if(iterator != mem.cbegin()) {
            iterator--;
            ret = iterator->second;
        }
    }
    if(ret.offset > address) {
        ret = MemoryInstance::null;
    }
    return ret;
}

int System::memoryLoop(SizeType offset, SizeType len, const void *data, bool write) const {
    int status = ERR_SUCCESS;
    while(len > 0) {
        MemoryInstance src = resolveAtMost(offset);
        if(!src) {
            status = ERR_BADRANGE;
        } else {
            SizeType srcOff = offset - src.offset;
            //No memory module covers the requested range
            if (srcOff >= src.length) {
                status = ERR_BADRANGE;
            }
            else {
                SizeType srcLen = std::min(src.length - srcOff, len);
                if(write) {
                    status = src.mod->writeMemory(srcOff, srcLen, data);
                } else {
                    status = src.mod->readMemory(srcOff, srcLen, /* HACK */(void*)(data));
                }
                len -= srcLen;
                offset += srcLen;
                data = advancePtr(data, srcLen);
            }
        }
        if(status != ERR_SUCCESS) {
            break;
        }
    }
    return status;
}<|endoftext|>