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

/**
 * @file
 * Describes a cache based on template policies.
 */

#ifndef __CACHE_HH__
#define __CACHE_HH__

#include "base/misc.hh" // fatal, panic, and warn

#include "mem/cache/base.hh"
#include "mem/cache/blk.hh"
#include "mem/cache/mshr.hh"

#include "sim/eventq.hh"

//Forward decleration
class BasePrefetcher;

/**
 * A template-policy based cache. The behavior of the cache can be altered by
 * supplying different template policies. TagStore handles all tag and data
 * storage @sa TagStore.
 */
template <class TagStore>
class Cache : public BaseCache
{
  public:
    /** Define the type of cache block to use. */
    typedef typename TagStore::BlkType BlkType;
    /** A typedef for a list of BlkType pointers. */
    typedef typename TagStore::BlkList BlkList;

    bool prefetchAccess;

  protected:

    class CpuSidePort : public CachePort
    {
      public:
        CpuSidePort(const std::string &_name,
                    Cache<TagStore> *_cache,
                    const std::string &_label,
                    std::vector<Range<Addr> > filterRanges);

        // BaseCache::CachePort just has a BaseCache *; this function
        // lets us get back the type info we lost when we stored the
        // cache pointer there.
        Cache<TagStore> *myCache() {
            return static_cast<Cache<TagStore> *>(cache);
        }

        virtual void getDeviceAddressRanges(AddrRangeList &resp,
                                            bool &snoop);

        virtual bool recvTiming(PacketPtr pkt);

        virtual Tick recvAtomic(PacketPtr pkt);

        virtual void recvFunctional(PacketPtr pkt);
    };

    class MemSidePort : public CachePort
    {
      public:
        MemSidePort(const std::string &_name,
                    Cache<TagStore> *_cache,
                    const std::string &_label,
                    std::vector<Range<Addr> > filterRanges);

        // BaseCache::CachePort just has a BaseCache *; this function
        // lets us get back the type info we lost when we stored the
        // cache pointer there.
        Cache<TagStore> *myCache() {
            return static_cast<Cache<TagStore> *>(cache);
        }

        void sendPacket();

        void processSendEvent();

        virtual void getDeviceAddressRanges(AddrRangeList &resp,
                                            bool &snoop);

        virtual bool recvTiming(PacketPtr pkt);

        virtual void recvRetry();

        virtual Tick recvAtomic(PacketPtr pkt);

        virtual void recvFunctional(PacketPtr pkt);

        typedef EventWrapper<MemSidePort, &MemSidePort::processSendEvent>
                SendEvent;
    };

    /** Tag and data Storage */
    TagStore *tags;

    /** Prefetcher */
    BasePrefetcher *prefetcher;

    /** Temporary cache block for occasional transitory use */
    BlkType *tempBlock;

    /**
     * Can this cache should allocate a block on a line-sized write miss.
     */
    const bool doFastWrites;

    const bool prefetchMiss;

    /**
     * Handle a replacement for the given request.
     * @param blk A pointer to the block, usually NULL
     * @param pkt The memory request to satisfy.
     * @param new_state The new state of the block.
     * @param writebacks A list to store any generated writebacks.
     */
    BlkType* doReplacement(BlkType *blk, PacketPtr pkt,
                           CacheBlk::State new_state, PacketList &writebacks);

    /**
     * Does all the processing necessary to perform the provided request.
     * @param pkt The memory request to perform.
     * @param lat The latency of the access.
     * @param writebacks List for any writebacks that need to be performed.
     * @param update True if the replacement data should be updated.
     * @return Pointer to the cache block touched by the request. NULL if it
     * was a miss.
     */
    bool access(PacketPtr pkt, BlkType *&blk,
                int &lat, PacketList &writebacks);

    /**
     *Handle doing the Compare and Swap function for SPARC.
     */
    void cmpAndSwap(BlkType *blk, PacketPtr pkt);

    /**
     * Find a block frame for new block at address addr, assuming that
     * the block is not currently in the cache.  Append writebacks if
     * any to provided packet list.  Return free block frame.  May
     * return NULL if there are no replaceable blocks at the moment.
     */
    BlkType *allocateBlock(Addr addr, PacketList &writebacks);

    /**
     * Populates a cache block and handles all outstanding requests for the
     * satisfied fill request. This version takes two memory requests. One
     * contains the fill data, the other is an optional target to satisfy.
     * Used for Cache::probe.
     * @param pkt The memory request with the fill data.
     * @param blk The cache block if it already exists.
     * @param writebacks List for any writebacks that need to be performed.
     * @return Pointer to the new cache block.
     */
    BlkType *handleFill(PacketPtr pkt, BlkType *blk,
                        PacketList &writebacks);

    void satisfyCpuSideRequest(PacketPtr pkt, BlkType *blk);
    bool satisfyMSHR(MSHR *mshr, PacketPtr pkt, BlkType *blk);

    void doTimingSupplyResponse(PacketPtr req_pkt, uint8_t *blk_data,
                                bool already_copied, bool pending_inval);

    /**
     * Sets the blk to the new state.
     * @param blk The cache block being snooped.
     * @param new_state The new coherence state for the block.
     */
    void handleSnoop(PacketPtr ptk, BlkType *blk,
                     bool is_timing, bool is_deferred, bool pending_inval);

    /**
     * Create a writeback request for the given block.
     * @param blk The block to writeback.
     * @return The writeback request for the block.
     */
    PacketPtr writebackBlk(BlkType *blk);

  public:
    /** Instantiates a basic cache object. */
    Cache(const Params *p, TagStore *tags, BasePrefetcher *prefetcher);

    virtual Port *getPort(const std::string &if_name, int idx = -1);
    virtual void deletePortRefs(Port *p);

    void regStats();

    /**
     * Performs the access specified by the request.
     * @param pkt The request to perform.
     * @return The result of the access.
     */
    bool timingAccess(PacketPtr pkt);

    /**
     * Performs the access specified by the request.
     * @param pkt The request to perform.
     * @return The result of the access.
     */
    Tick atomicAccess(PacketPtr pkt);

    /**
     * Performs the access specified by the request.
     * @param pkt The request to perform.
     * @return The result of the access.
     */
    void functionalAccess(PacketPtr pkt, CachePort *incomingPort,
                          CachePort *otherSidePort);

    /**
     * Handles a response (cache line fill/write ack) from the bus.
     * @param pkt The request being responded to.
     */
    void handleResponse(PacketPtr pkt);

    /**
     * Snoops bus transactions to maintain coherence.
     * @param pkt The current bus transaction.
     */
    void snoopTiming(PacketPtr pkt);

    /**
     * Snoop for the provided request in the cache and return the estimated
     * time of completion.
     * @param pkt The memory request to snoop
     * @return The estimated completion time.
     */
    Tick snoopAtomic(PacketPtr pkt);

    /**
     * Squash all requests associated with specified thread.
     * intended for use by I-cache.
     * @param threadNum The thread to squash.
     */
    void squash(int threadNum);

    /**
     * Generate an appropriate downstream bus request packet for the
     * given parameters.
     * @param cpu_pkt  The upstream request that needs to be satisfied.
     * @param blk The block currently in the cache corresponding to
     * cpu_pkt (NULL if none).
     * @param needsExclusive  Indicates that an exclusive copy is required
     * even if the request in cpu_pkt doesn't indicate that.
     * @return A new Packet containing the request, or NULL if the
     * current request in cpu_pkt should just be forwarded on.
     */
    PacketPtr getBusPacket(PacketPtr cpu_pkt, BlkType *blk,
                           bool needsExclusive);

    /**
     * Return the next MSHR to service, either a pending miss from the
     * mshrQueue, a buffered write from the write buffer, or something
     * from the prefetcher.  This function is responsible for
     * prioritizing among those sources on the fly.
     */
    MSHR *getNextMSHR();

    /**
     * Selects an outstanding request to service.  Called when the
     * cache gets granted the downstream bus in timing mode.
     * @return The request to service, NULL if none found.
     */
    PacketPtr getTimingPacket();

    /**
     * Marks a request as in service (sent on the bus). This can have side
     * effect since storage for no response commands is deallocated once they
     * are successfully sent.
     * @param pkt The request that was sent on the bus.
     */
    void markInService(MSHR *mshr);

    /**
     * Perform the given writeback request.
     * @param pkt The writeback request.
     */
    void doWriteback(PacketPtr pkt);

    /**
     * Return whether there are any outstanding misses.
     */
    bool outstandingMisses() const
    {
        return mshrQueue.allocated != 0;
    }

    CacheBlk *findBlock(Addr addr) {
        return tags->findBlock(addr);
    }

    bool inCache(Addr addr) {
        return (tags->findBlock(addr) != 0);
    }

    bool inMissQueue(Addr addr) {
        return (mshrQueue.findMatch(addr) != 0);
    }
};

#endif // __CACHE_HH__
<commit_msg>This function declaration isn't used anywhere.  HG: user: Lisa Hsu <hsul@eecs.umich.edu> HG: branch default HG: changed src/mem/cache/cache.hh<commit_after>/*
 * Copyright (c) 2002-2005 The Regents of The University of Michigan
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met: redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer;
 * redistributions in binary form must reproduce the above copyright
 * notice, this list of conditions and the following disclaimer in the
 * documentation and/or other materials provided with the distribution;
 * neither the name of the copyright holders nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * Authors: Erik Hallnor
 *          Dave Greene
 *          Steve Reinhardt
 *          Ron Dreslinski
 */

/**
 * @file
 * Describes a cache based on template policies.
 */

#ifndef __CACHE_HH__
#define __CACHE_HH__

#include "base/misc.hh" // fatal, panic, and warn

#include "mem/cache/base.hh"
#include "mem/cache/blk.hh"
#include "mem/cache/mshr.hh"

#include "sim/eventq.hh"

//Forward decleration
class BasePrefetcher;

/**
 * A template-policy based cache. The behavior of the cache can be altered by
 * supplying different template policies. TagStore handles all tag and data
 * storage @sa TagStore.
 */
template <class TagStore>
class Cache : public BaseCache
{
  public:
    /** Define the type of cache block to use. */
    typedef typename TagStore::BlkType BlkType;
    /** A typedef for a list of BlkType pointers. */
    typedef typename TagStore::BlkList BlkList;

    bool prefetchAccess;

  protected:

    class CpuSidePort : public CachePort
    {
      public:
        CpuSidePort(const std::string &_name,
                    Cache<TagStore> *_cache,
                    const std::string &_label,
                    std::vector<Range<Addr> > filterRanges);

        // BaseCache::CachePort just has a BaseCache *; this function
        // lets us get back the type info we lost when we stored the
        // cache pointer there.
        Cache<TagStore> *myCache() {
            return static_cast<Cache<TagStore> *>(cache);
        }

        virtual void getDeviceAddressRanges(AddrRangeList &resp,
                                            bool &snoop);

        virtual bool recvTiming(PacketPtr pkt);

        virtual Tick recvAtomic(PacketPtr pkt);

        virtual void recvFunctional(PacketPtr pkt);
    };

    class MemSidePort : public CachePort
    {
      public:
        MemSidePort(const std::string &_name,
                    Cache<TagStore> *_cache,
                    const std::string &_label,
                    std::vector<Range<Addr> > filterRanges);

        // BaseCache::CachePort just has a BaseCache *; this function
        // lets us get back the type info we lost when we stored the
        // cache pointer there.
        Cache<TagStore> *myCache() {
            return static_cast<Cache<TagStore> *>(cache);
        }

        void sendPacket();

        void processSendEvent();

        virtual void getDeviceAddressRanges(AddrRangeList &resp,
                                            bool &snoop);

        virtual bool recvTiming(PacketPtr pkt);

        virtual void recvRetry();

        virtual Tick recvAtomic(PacketPtr pkt);

        virtual void recvFunctional(PacketPtr pkt);

        typedef EventWrapper<MemSidePort, &MemSidePort::processSendEvent>
                SendEvent;
    };

    /** Tag and data Storage */
    TagStore *tags;

    /** Prefetcher */
    BasePrefetcher *prefetcher;

    /** Temporary cache block for occasional transitory use */
    BlkType *tempBlock;

    /**
     * Can this cache should allocate a block on a line-sized write miss.
     */
    const bool doFastWrites;

    const bool prefetchMiss;

    /**
     * Does all the processing necessary to perform the provided request.
     * @param pkt The memory request to perform.
     * @param lat The latency of the access.
     * @param writebacks List for any writebacks that need to be performed.
     * @param update True if the replacement data should be updated.
     * @return Pointer to the cache block touched by the request. NULL if it
     * was a miss.
     */
    bool access(PacketPtr pkt, BlkType *&blk,
                int &lat, PacketList &writebacks);

    /**
     *Handle doing the Compare and Swap function for SPARC.
     */
    void cmpAndSwap(BlkType *blk, PacketPtr pkt);

    /**
     * Find a block frame for new block at address addr, assuming that
     * the block is not currently in the cache.  Append writebacks if
     * any to provided packet list.  Return free block frame.  May
     * return NULL if there are no replaceable blocks at the moment.
     */
    BlkType *allocateBlock(Addr addr, PacketList &writebacks);

    /**
     * Populates a cache block and handles all outstanding requests for the
     * satisfied fill request. This version takes two memory requests. One
     * contains the fill data, the other is an optional target to satisfy.
     * Used for Cache::probe.
     * @param pkt The memory request with the fill data.
     * @param blk The cache block if it already exists.
     * @param writebacks List for any writebacks that need to be performed.
     * @return Pointer to the new cache block.
     */
    BlkType *handleFill(PacketPtr pkt, BlkType *blk,
                        PacketList &writebacks);

    void satisfyCpuSideRequest(PacketPtr pkt, BlkType *blk);
    bool satisfyMSHR(MSHR *mshr, PacketPtr pkt, BlkType *blk);

    void doTimingSupplyResponse(PacketPtr req_pkt, uint8_t *blk_data,
                                bool already_copied, bool pending_inval);

    /**
     * Sets the blk to the new state.
     * @param blk The cache block being snooped.
     * @param new_state The new coherence state for the block.
     */
    void handleSnoop(PacketPtr ptk, BlkType *blk,
                     bool is_timing, bool is_deferred, bool pending_inval);

    /**
     * Create a writeback request for the given block.
     * @param blk The block to writeback.
     * @return The writeback request for the block.
     */
    PacketPtr writebackBlk(BlkType *blk);

  public:
    /** Instantiates a basic cache object. */
    Cache(const Params *p, TagStore *tags, BasePrefetcher *prefetcher);

    virtual Port *getPort(const std::string &if_name, int idx = -1);
    virtual void deletePortRefs(Port *p);

    void regStats();

    /**
     * Performs the access specified by the request.
     * @param pkt The request to perform.
     * @return The result of the access.
     */
    bool timingAccess(PacketPtr pkt);

    /**
     * Performs the access specified by the request.
     * @param pkt The request to perform.
     * @return The result of the access.
     */
    Tick atomicAccess(PacketPtr pkt);

    /**
     * Performs the access specified by the request.
     * @param pkt The request to perform.
     * @return The result of the access.
     */
    void functionalAccess(PacketPtr pkt, CachePort *incomingPort,
                          CachePort *otherSidePort);

    /**
     * Handles a response (cache line fill/write ack) from the bus.
     * @param pkt The request being responded to.
     */
    void handleResponse(PacketPtr pkt);

    /**
     * Snoops bus transactions to maintain coherence.
     * @param pkt The current bus transaction.
     */
    void snoopTiming(PacketPtr pkt);

    /**
     * Snoop for the provided request in the cache and return the estimated
     * time of completion.
     * @param pkt The memory request to snoop
     * @return The estimated completion time.
     */
    Tick snoopAtomic(PacketPtr pkt);

    /**
     * Squash all requests associated with specified thread.
     * intended for use by I-cache.
     * @param threadNum The thread to squash.
     */
    void squash(int threadNum);

    /**
     * Generate an appropriate downstream bus request packet for the
     * given parameters.
     * @param cpu_pkt  The upstream request that needs to be satisfied.
     * @param blk The block currently in the cache corresponding to
     * cpu_pkt (NULL if none).
     * @param needsExclusive  Indicates that an exclusive copy is required
     * even if the request in cpu_pkt doesn't indicate that.
     * @return A new Packet containing the request, or NULL if the
     * current request in cpu_pkt should just be forwarded on.
     */
    PacketPtr getBusPacket(PacketPtr cpu_pkt, BlkType *blk,
                           bool needsExclusive);

    /**
     * Return the next MSHR to service, either a pending miss from the
     * mshrQueue, a buffered write from the write buffer, or something
     * from the prefetcher.  This function is responsible for
     * prioritizing among those sources on the fly.
     */
    MSHR *getNextMSHR();

    /**
     * Selects an outstanding request to service.  Called when the
     * cache gets granted the downstream bus in timing mode.
     * @return The request to service, NULL if none found.
     */
    PacketPtr getTimingPacket();

    /**
     * Marks a request as in service (sent on the bus). This can have side
     * effect since storage for no response commands is deallocated once they
     * are successfully sent.
     * @param pkt The request that was sent on the bus.
     */
    void markInService(MSHR *mshr);

    /**
     * Perform the given writeback request.
     * @param pkt The writeback request.
     */
    void doWriteback(PacketPtr pkt);

    /**
     * Return whether there are any outstanding misses.
     */
    bool outstandingMisses() const
    {
        return mshrQueue.allocated != 0;
    }

    CacheBlk *findBlock(Addr addr) {
        return tags->findBlock(addr);
    }

    bool inCache(Addr addr) {
        return (tags->findBlock(addr) != 0);
    }

    bool inMissQueue(Addr addr) {
        return (mshrQueue.findMatch(addr) != 0);
    }
};

#endif // __CACHE_HH__
<|endoftext|>


<commit_before>/*******************************************************************************
 * Reverse Polish Notation calculator.                                         *
 * Copyright (c) 2007-2009, Samuel Fredrickson <kinghajj@gmail.com>            *
 * All rights reserved.                                                        *
 *                                                                             *
 * Redistribution and use in source and binary forms, with or without          *
 * modification, are permitted provided that the following conditions are met: *
 *     * Redistributions of source code must retain the above copyright        *
 *       notice, this list of conditions and the following disclaimer.         *
 *     * Redistributions in binary form must reproduce the above copyright     *
 *       notice, this list of conditions and the following disclaimer in the   *
 *       documentation and/or other materials provided with the distribution.  *
 *                                                                             *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER ``AS IS'' AND ANY EXPRESS *
 * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED           *
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE      *
 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY        *
 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES  *
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR          *
 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER  *
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT          *
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY   *
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH *
 * DAMAGE.                                                                     *
 ******************************************************************************/

/*******************************************************************************
 * Operators.cpp - operator functions.                                         *
 ******************************************************************************/

#include "rpn.h"
#include <cmath>
using namespace std;
using namespace RPN;

#ifndef DOXYGEN_SKIP

static Value addition(Value a, Value b)
{
    return a + b;
}

static Value subtraction(Value a, Value b)
{
    return a - b;
}

static Value multiplication(Value a, Value b)
{
    return a * b;
}

static Value division(Value a, Value b)
{
    return a / b;
}

static Value power(Value a, Value b)
{
#ifdef RPN_DOUBLE
    return pow(a, b);
#elif  RPN_LONG_DOUBLE
    return powl(a, b);
#endif
}

static Value equals(Value a, Value b)
{
    return a == b ? 1 : 0;
}

static Value modulo(Value a, Value b)
{
    return (long)a % (long)b;
}

static Value _xor(Value a, Value b)
{
    return (long)a ^ (long)b;
}

static Value _and(Value a, Value b)
{
    return (long)a & (long)b;
}

static Value _or(Value a, Value b)
{
    return (long)a | (long)b;
}

#endif

Operators RPN::defaultOperators()
{
    Operators ret;

    ret["+"]  = addition;
    ret["-"]  = subtraction;
    ret["*"]  = multiplication;
    ret["/"]  = division;
    ret["**"] = power;
    ret["="]  = equals;
    ret["%"]  = modulo;
    ret["^"]  = _xor;
    ret["&"]  = _and;
    ret["|"]  = _or;

    return ret;
}
<commit_msg>Added a general logarithm function.<commit_after>/*******************************************************************************
 * Reverse Polish Notation calculator.                                         *
 * Copyright (c) 2007-2009, Samuel Fredrickson <kinghajj@gmail.com>            *
 * All rights reserved.                                                        *
 *                                                                             *
 * Redistribution and use in source and binary forms, with or without          *
 * modification, are permitted provided that the following conditions are met: *
 *     * Redistributions of source code must retain the above copyright        *
 *       notice, this list of conditions and the following disclaimer.         *
 *     * Redistributions in binary form must reproduce the above copyright     *
 *       notice, this list of conditions and the following disclaimer in the   *
 *       documentation and/or other materials provided with the distribution.  *
 *                                                                             *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER ``AS IS'' AND ANY EXPRESS *
 * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED           *
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE      *
 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY        *
 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES  *
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR          *
 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER  *
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT          *
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY   *
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH *
 * DAMAGE.                                                                     *
 ******************************************************************************/

/*******************************************************************************
 * Operators.cpp - operator functions.                                         *
 ******************************************************************************/

#include "rpn.h"
#include <cmath>
using namespace std;
using namespace RPN;

#ifndef DOXYGEN_SKIP

static Value addition(Value a, Value b)
{
    return a + b;
}

static Value subtraction(Value a, Value b)
{
    return a - b;
}

static Value multiplication(Value a, Value b)
{
    return a * b;
}

static Value division(Value a, Value b)
{
    return a / b;
}

static Value power(Value a, Value b)
{
#ifdef RPN_DOUBLE
    return pow(a, b);
#elif  RPN_LONG_DOUBLE
    return powl(a, b);
#endif
}

static Value equals(Value a, Value b)
{
    return a == b ? 1 : 0;
}

static Value modulo(Value a, Value b)
{
    return (long)a % (long)b;
}

static Value _xor(Value a, Value b)
{
    return (long)a ^ (long)b;
}

static Value _and(Value a, Value b)
{
    return (long)a & (long)b;
}

static Value _or(Value a, Value b)
{
    return (long)a | (long)b;
}

static Value _log(Value b, Value e)
{
    return log(e) / log(b);
}

#endif

Operators RPN::defaultOperators()
{
    Operators ret;

    ret["+"]   = addition;
    ret["-"]   = subtraction;
    ret["*"]   = multiplication;
    ret["/"]   = division;
    ret["**"]  = power;
    ret["="]   = equals;
    ret["%"]   = modulo;
    ret["^"]   = _xor;
    ret["&"]   = _and;
    ret["|"]   = _or;
    ret["log"] = _log;

    return ret;
}
<|endoftext|>


<commit_before>#include "gtest/gtest.h"

#include "dioptre/locator.h"
#include "dioptre/module.h"
#include "dioptre/window/window_interface.h"
#include "dioptre/graphics/graphics_interface.h"

using dioptre::window::WindowInterface;
using dioptre::graphics::GraphicsInterface;

TEST(Locator, DefaultWindow) {
  dioptre::Locator::initialize();
  WindowInterface* window = dioptre::Locator::getInstance<WindowInterface>(dioptre::Module::M_WINDOW);

  EXPECT_EQ(window->create(), 0);
}

TEST(Locator, DefaultGraphics) {
  dioptre::Locator::initialize();
  GraphicsInterface* graphics = dioptre::Locator::getInstance<GraphicsInterface>(dioptre::Module::M_GRAPHICS);

  EXPECT_EQ(graphics->Initialize(), 0);
}

class MockGraphics : public GraphicsInterface {
public:
  int Initialize() { return 1337; }
  void Resize(int width, int height) {  }
  void Render() { }
  void Destroy() { }
};

TEST(Locator, Provide) {
  dioptre::Locator::initialize();

  MockGraphics* mockGraphics = new MockGraphics();
  dioptre::Locator::provide(dioptre::Module::M_GRAPHICS, mockGraphics);

  EXPECT_EQ(dioptre::Locator::getInstance<GraphicsInterface>(dioptre::Module::M_GRAPHICS), mockGraphics);
}

TEST(Locator, ProvideNull) {
  dioptre::Locator::initialize();
  auto nullGraphics = dioptre::Locator::getInstance<GraphicsInterface>(dioptre::Module::M_GRAPHICS);

  MockGraphics* mockGraphics = new MockGraphics();
  dioptre::Locator::provide(dioptre::Module::M_GRAPHICS, mockGraphics);
  dioptre::Locator::provide(dioptre::Module::M_GRAPHICS, nullptr);

  EXPECT_EQ(dioptre::Locator::getInstance<GraphicsInterface>(dioptre::Module::M_GRAPHICS), nullGraphics);
}
<commit_msg>use service locator<commit_after>#include "gtest/gtest.h"

#include "dioptre/locator.h"
#include "dioptre/module.h"
#include "dioptre/window/window_interface.h"
#include "dioptre/graphics/graphics_interface.h"

using dioptre::window::WindowInterface;
using dioptre::graphics::GraphicsInterface;

TEST(Locator, DefaultWindow) {
  dioptre::Locator::initialize();
  WindowInterface* window = dioptre::Locator::getInstance<WindowInterface>(dioptre::Module::M_WINDOW);

  EXPECT_EQ(window->create(), 0);
}

TEST(Locator, DefaultGraphics) {
  dioptre::Locator::initialize();
  GraphicsInterface* graphics = dioptre::Locator::getInstance<GraphicsInterface>(dioptre::Module::M_GRAPHICS);

  EXPECT_EQ(graphics->Initialize(), 0);
}

class MockGraphics : public GraphicsInterface {
public:
  int Initialize() { return 1337; }
  void Resize(int width, int height) {  }
  void Render() { }
  void Destroy() { }
};

TEST(Locator, Provide) {
  dioptre::Locator::initialize();

  MockGraphics* mockGraphics = new MockGraphics();
  dioptre::Locator::provide(dioptre::Module::M_GRAPHICS, mockGraphics);

  EXPECT_EQ(dioptre::Locator::getInstance<GraphicsInterface>(dioptre::Module::M_GRAPHICS), mockGraphics);
}

TEST(Locator, ProvideNull) {
  dioptre::Locator::initialize();
  auto nullGraphics = dioptre::Locator::getInstance<GraphicsInterface>(dioptre::Module::M_GRAPHICS);

  MockGraphics* mockGraphics = new MockGraphics();
  dioptre::Locator::provide(dioptre::Module::M_GRAPHICS, mockGraphics);
  dioptre::Locator::provide(dioptre::Module::M_GRAPHICS, nullptr);

  // Setting it to nullptr does revert back to default
  EXPECT_EQ(dioptre::Locator::getInstance<GraphicsInterface>(dioptre::Module::M_GRAPHICS), nullGraphics);
}
<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: EventOASISTContext.cxx,v $
 *
 *  $Revision: 1.7 $
 *
 *  last change: $Author: obo $ $Date: 2006-09-17 11:23:18 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/

// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_xmloff.hxx"

#ifndef _XMLOFF_EVENTOASISTCONTEXT_HXX
#include "EventOASISTContext.hxx"
#endif
#ifndef _XMLOFF_EVENTMAP_HXX
#include "EventMap.hxx"
#endif
#ifndef _XMLOFF_MUTABLEATTRLIST_HXX
#include "MutableAttrList.hxx"
#endif
#ifndef _XMLOFF_XMLNMSPE_HXX
#include "xmlnmspe.hxx"
#endif
#ifndef _XMLOFF_ACTIONMAPTYPESOASIS_HXX
#include "ActionMapTypesOASIS.hxx"
#endif
#ifndef _XMLOFF_ATTRTRANSFORMERACTION_HXX
#include "AttrTransformerAction.hxx"
#endif
#ifndef _XMLOFF_TRANSFORMERACTIONS_HXX
#include "TransformerActions.hxx"
#endif
#ifndef _XMLOFF_TRANSFORMERBASE_HXX
#include "TransformerBase.hxx"
#endif

#ifndef OASIS_FILTER_OOO_1X
// Used to parse Scripting Framework URLs
#ifndef _COM_SUN_STAR_URI_XURIREFERENCEFACTORY_HPP_
#include <com/sun/star/uri/XUriReferenceFactory.hpp>
#endif
#ifndef _COM_SUN_STAR_URI_XVNDSUNSTARSCRIPTURL_HPP_
#include <com/sun/star/uri/XVndSunStarScriptUrl.hpp>
#endif
#include <comphelper/processfactory.hxx>
#endif

#include <hash_map>

using namespace ::rtl;
using namespace ::com::sun::star::uno;
using namespace ::com::sun::star::xml::sax;
using namespace ::xmloff::token;

class XMLTransformerOASISEventMap_Impl:
    public ::std::hash_map< NameKey_Impl, ::rtl::OUString,
                            NameHash_Impl, NameHash_Impl >
{
public:
    XMLTransformerOASISEventMap_Impl( XMLTransformerEventMapEntry *pInit );
    ~XMLTransformerOASISEventMap_Impl();
};

XMLTransformerOASISEventMap_Impl::XMLTransformerOASISEventMap_Impl( XMLTransformerEventMapEntry *pInit )
{
    if( pInit )
    {
        XMLTransformerOASISEventMap_Impl::key_type aKey;
        XMLTransformerOASISEventMap_Impl::data_type aData;
        while( pInit->m_pOASISName )
        {
            aKey.m_nPrefix = pInit->m_nOASISPrefix;
            aKey.m_aLocalName = OUString::createFromAscii(pInit->m_pOASISName);

            OSL_ENSURE( find( aKey ) == end(), "duplicate event map entry" );

            aData = OUString::createFromAscii(pInit->m_pOOoName);

            XMLTransformerOASISEventMap_Impl::value_type aVal( aKey, aData );

            insert( aVal );
            ++pInit;
        }
    }
}

XMLTransformerOASISEventMap_Impl::~XMLTransformerOASISEventMap_Impl()
{
}

// -----------------------------------------------------------------------------

TYPEINIT1( XMLEventOASISTransformerContext, XMLRenameElemTransformerContext);

XMLEventOASISTransformerContext::XMLEventOASISTransformerContext(
        XMLTransformerBase& rImp,
        const OUString& rQName ) :
    XMLRenameElemTransformerContext( rImp, rQName,
         rImp.GetNamespaceMap().GetKeyByAttrName( rQName ), XML_EVENT )
{
}

XMLEventOASISTransformerContext::~XMLEventOASISTransformerContext()
{
}

XMLTransformerOASISEventMap_Impl
    *XMLEventOASISTransformerContext::CreateEventMap()
{
    return new XMLTransformerOASISEventMap_Impl( aTransformerEventMap );
}

XMLTransformerOASISEventMap_Impl
    *XMLEventOASISTransformerContext::CreateFormEventMap()
{
    return new XMLTransformerOASISEventMap_Impl( aFormTransformerEventMap );
}

void XMLEventOASISTransformerContext::FlushEventMap(
        XMLTransformerOASISEventMap_Impl *p )
{
    delete p;
}

OUString XMLEventOASISTransformerContext::GetEventName(
        sal_uInt16 nPrefix,
        const OUString& rName,
           XMLTransformerOASISEventMap_Impl& rMap,
           XMLTransformerOASISEventMap_Impl *pMap2)
{
    XMLTransformerOASISEventMap_Impl::key_type aKey( nPrefix, rName );
    if( pMap2 )
    {
        XMLTransformerOASISEventMap_Impl::const_iterator aIter =
            pMap2->find( aKey );
        if( !(aIter == pMap2->end()) )
            return (*aIter).second;
    }

    XMLTransformerOASISEventMap_Impl::const_iterator aIter = rMap.find( aKey );
    if( aIter == rMap.end() )
        return rName;
    else
        return (*aIter).second;
}

bool ParseURLAsString(
    const OUString& rAttrValue,
    OUString* pName, OUString* pLocation )
{
    OUString SCHEME( RTL_CONSTASCII_USTRINGPARAM( "vnd.sun.star.script:" ) );

    sal_Int32 params = rAttrValue.indexOf( '?' );
    if ( rAttrValue.indexOf( SCHEME ) != 0 || params < 0 )
    {
        return FALSE;
    }

    sal_Int32 start = SCHEME.getLength();
    *pName = rAttrValue.copy( start, params - start );

    OUString aToken;
    OUString aLanguage;
    params++;
    do
    {
        aToken = rAttrValue.getToken( 0, '&', params );
        sal_Int32 dummy = 0;

        if ( aToken.match( GetXMLToken( XML_LANGUAGE ) ) )
        {
            aLanguage = aToken.getToken( 1, '=', dummy );
        }
        else if ( aToken.match( GetXMLToken( XML_LOCATION ) ) )
        {
            OUString tmp = aToken.getToken( 1, '=', dummy );
            if ( tmp.equalsIgnoreAsciiCase( GetXMLToken( XML_DOCUMENT ) ) )
            {
                *pLocation = GetXMLToken( XML_DOCUMENT );
            }
            else
            {
                *pLocation = GetXMLToken( XML_APPLICATION );
            }
        }
    } while ( params >= 0 );

    if ( aLanguage.equalsIgnoreAsciiCaseAscii( "basic" ) )
    {
        return TRUE;
    }
    return FALSE;
}

bool ParseURL(
    const OUString& rAttrValue,
    OUString* pName, OUString* pLocation )
{
#ifdef OASIS_FILTER_OOO_1X
    return ParseURLAsString( rAttrValue, pName, pLocation );
#else
    Reference< com::sun::star::lang::XMultiServiceFactory >
        xSMgr = ::comphelper::getProcessServiceFactory();

    Reference< com::sun::star::uri::XUriReferenceFactory >
        xFactory( xSMgr->createInstance( OUString::createFromAscii(
            "com.sun.star.uri.UriReferenceFactory" ) ), UNO_QUERY );

    if ( xFactory.is() )
    {
        Reference< com::sun::star::uri::XVndSunStarScriptUrl > xUrl (
            xFactory->parse( rAttrValue ), UNO_QUERY );

        if ( xUrl.is() )
        {
            OUString aLanguageKey = GetXMLToken( XML_LANGUAGE );
            if ( xUrl.is() && xUrl->hasParameter( aLanguageKey ) )
            {
                OUString aLanguage = xUrl->getParameter( aLanguageKey );

                if ( aLanguage.equalsIgnoreAsciiCaseAscii( "basic" ) )
                {
                    *pName = xUrl->getName();

                    OUString tmp =
                        xUrl->getParameter( GetXMLToken( XML_LOCATION ) );

                    OUString doc = GetXMLToken( XML_DOCUMENT );

                    if ( tmp.equalsIgnoreAsciiCase( doc ) )
                    {
                        *pLocation = doc;
                    }
                    else
                    {
                        *pLocation = GetXMLToken( XML_APPLICATION );
                    }
                    return TRUE;
                }
            }
        }
        return FALSE;
    }
    else
    {
        return ParseURLAsString( rAttrValue, pName, pLocation );
    }
#endif
}

void XMLEventOASISTransformerContext::StartElement(
    const Reference< XAttributeList >& rAttrList )
{
    OSL_TRACE("XMLEventOASISTransformerContext::StartElement");

    XMLTransformerActions *pActions =
        GetTransformer().GetUserDefinedActions( OASIS_EVENT_ACTIONS );
    OSL_ENSURE( pActions, "go no actions" );

    Reference< XAttributeList > xAttrList( rAttrList );
    XMLMutableAttributeList *pMutableAttrList = 0;
    sal_Int16 nAttrCount = xAttrList.is() ? xAttrList->getLength() : 0;
    for( sal_Int16 i=0; i < nAttrCount; i++ )
    {
        const OUString& rAttrName = xAttrList->getNameByIndex( i );
        OUString aLocalName;
        sal_uInt16 nPrefix =
            GetTransformer().GetNamespaceMap().GetKeyByAttrName( rAttrName,
                                                                 &aLocalName );
        XMLTransformerActions::key_type aKey( nPrefix, aLocalName );
        XMLTransformerActions::const_iterator aIter =
            pActions->find( aKey );
        if( !(aIter == pActions->end() ) )
        {
            if( !pMutableAttrList )
            {
                pMutableAttrList =
                        new XMLMutableAttributeList( xAttrList );
                xAttrList = pMutableAttrList;
            }
            const OUString& rAttrValue = xAttrList->getValueByIndex( i );
            switch( (*aIter).second.m_nActionType )
            {
            case XML_ATACTION_HREF:
                {
                    OUString aAttrValue( rAttrValue );
                    OUString aName, aLocation;

                    bool bNeedsTransform =
                        ParseURL( rAttrValue, &aName, &aLocation );

                    if ( bNeedsTransform )
                    {
                        pMutableAttrList->RemoveAttributeByIndex( i );

                        OUString aAttrQName(
                            GetTransformer().GetNamespaceMap().GetQNameByKey(
                                XML_NAMESPACE_SCRIPT,
                            ::xmloff::token::GetXMLToken( XML_MACRO_NAME ) ) );

                        pMutableAttrList->AddAttribute( aAttrQName, aName );

                        sal_Int16 idx = pMutableAttrList->GetIndexByName(
                            GetTransformer().GetNamespaceMap().GetQNameByKey(
                                XML_NAMESPACE_SCRIPT,
                            GetXMLToken( XML_LANGUAGE ) ) );

                        pMutableAttrList->SetValueByIndex( idx,
                            OUString::createFromAscii("StarBasic") );

                        OUString aLocQName(
                            GetTransformer().GetNamespaceMap().GetQNameByKey(
                                XML_NAMESPACE_SCRIPT,
                                GetXMLToken( XML_LOCATION ) ) );

                        pMutableAttrList->AddAttribute( aLocQName, aLocation );
                    }
                }
                break;
            case XML_ATACTION_EVENT_NAME:
                {
                    // Check if the event belongs to a form or control by
                    // cehcking the 2nd ancestor element, f.i.:
                    // <form:button><form:event-listeners><form:event-listener>
                    const XMLTransformerContext *pObjContext =
                        GetTransformer().GetAncestorContext( 1 );
                    sal_Bool bForm = pObjContext &&

                        pObjContext->HasNamespace(XML_NAMESPACE_FORM );
                    pMutableAttrList->SetValueByIndex( i,
                                   GetTransformer().GetEventName( rAttrValue,
                                                                    bForm ) );
                }
                break;
            case XML_ATACTION_REMOVE_NAMESPACE_PREFIX:
                {
                    OUString aAttrValue( rAttrValue );
                    sal_uInt16 nValPrefix =
                        static_cast<sal_uInt16>((*aIter).second.m_nParam1);
                    if( GetTransformer().RemoveNamespacePrefix(
                                aAttrValue, nValPrefix ) )
                        pMutableAttrList->SetValueByIndex( i, aAttrValue );
                }
                break;
            case XML_ATACTION_MACRO_NAME:
            {
                OUString aName, aLocation;
                bool bNeedsTransform =
                ParseURL( rAttrValue, &aName, &aLocation );

                if ( bNeedsTransform )
                {
                    pMutableAttrList->SetValueByIndex( i, aName );

                    sal_Int16 idx = pMutableAttrList->GetIndexByName(
                    GetTransformer().GetNamespaceMap().GetQNameByKey(
                    XML_NAMESPACE_SCRIPT,
                    GetXMLToken( XML_LANGUAGE ) ) );

                    pMutableAttrList->SetValueByIndex( idx,
                    OUString::createFromAscii("StarBasic") );

                    OUString aLocQName(
                    GetTransformer().GetNamespaceMap().GetQNameByKey(
                    XML_NAMESPACE_SCRIPT,
                    GetXMLToken( XML_LOCATION ) ) );

                    pMutableAttrList->AddAttribute( aLocQName, aLocation );
                }
                else
                {
                    const OUString& rApp = GetXMLToken( XML_APPLICATION );
                    const OUString& rDoc = GetXMLToken( XML_DOCUMENT );
                    OUString aAttrValue;
                    if( rAttrValue.getLength() > rApp.getLength()+1 &&
                        rAttrValue.copy(0,rApp.getLength()).
                            equalsIgnoreAsciiCase( rApp ) &&
                        ':' == rAttrValue[rApp.getLength()] )
                    {
                        aLocation = rApp;
                        aAttrValue = rAttrValue.copy( rApp.getLength()+1 );
                    }
                    else if( rAttrValue.getLength() > rDoc.getLength()+1 &&
                             rAttrValue.copy(0,rDoc.getLength()).
                                equalsIgnoreAsciiCase( rDoc ) &&
                             ':' == rAttrValue[rDoc.getLength()] )
                    {
                        aLocation= rDoc;
                        aAttrValue = rAttrValue.copy( rDoc.getLength()+1 );
                    }
                    if( aAttrValue.getLength() )
                        pMutableAttrList->SetValueByIndex( i,
                    aAttrValue );
                    if( aLocation.getLength() )
                    {
                        OUString aAttrQName( GetTransformer().GetNamespaceMap().
                        GetQNameByKey( XML_NAMESPACE_SCRIPT,
                        ::xmloff::token::GetXMLToken( XML_LOCATION ) ) );
                        pMutableAttrList->AddAttribute( aAttrQName, aLocation );
                        // draw bug
                        aAttrQName = GetTransformer().GetNamespaceMap().
                        GetQNameByKey( XML_NAMESPACE_SCRIPT,
                        ::xmloff::token::GetXMLToken( XML_LIBRARY ) );
                        pMutableAttrList->AddAttribute( aAttrQName, aLocation );
                    }
                }
            }
            break;
            case XML_ATACTION_COPY:
                break;
            default:
                OSL_ENSURE( !this, "unknown action" );
                break;
            }
        }
    }

    XMLRenameElemTransformerContext::StartElement( xAttrList );
}
<commit_msg>INTEGRATION: CWS impresstables2 (1.7.80); FILE MERGED 2007/07/27 09:10:00 cl 1.7.80.1: fixed build issues due to pch and namespace ::rtl<commit_after>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: EventOASISTContext.cxx,v $
 *
 *  $Revision: 1.8 $
 *
 *  last change: $Author: rt $ $Date: 2008-03-12 11:14:00 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/

// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_xmloff.hxx"

#ifndef _XMLOFF_EVENTOASISTCONTEXT_HXX
#include "EventOASISTContext.hxx"
#endif
#ifndef _XMLOFF_EVENTMAP_HXX
#include "EventMap.hxx"
#endif
#ifndef _XMLOFF_MUTABLEATTRLIST_HXX
#include "MutableAttrList.hxx"
#endif
#ifndef _XMLOFF_XMLNMSPE_HXX
#include "xmlnmspe.hxx"
#endif
#ifndef _XMLOFF_ACTIONMAPTYPESOASIS_HXX
#include "ActionMapTypesOASIS.hxx"
#endif
#ifndef _XMLOFF_ATTRTRANSFORMERACTION_HXX
#include "AttrTransformerAction.hxx"
#endif
#ifndef _XMLOFF_TRANSFORMERACTIONS_HXX
#include "TransformerActions.hxx"
#endif
#ifndef _XMLOFF_TRANSFORMERBASE_HXX
#include "TransformerBase.hxx"
#endif

#ifndef OASIS_FILTER_OOO_1X
// Used to parse Scripting Framework URLs
#ifndef _COM_SUN_STAR_URI_XURIREFERENCEFACTORY_HPP_
#include <com/sun/star/uri/XUriReferenceFactory.hpp>
#endif
#ifndef _COM_SUN_STAR_URI_XVNDSUNSTARSCRIPTURL_HPP_
#include <com/sun/star/uri/XVndSunStarScriptUrl.hpp>
#endif
#include <comphelper/processfactory.hxx>
#endif

#include <hash_map>

using ::rtl::OUString;

using namespace ::com::sun::star::uno;
using namespace ::com::sun::star::xml::sax;
using namespace ::xmloff::token;

class XMLTransformerOASISEventMap_Impl:
    public ::std::hash_map< NameKey_Impl, ::rtl::OUString,
                            NameHash_Impl, NameHash_Impl >
{
public:
    XMLTransformerOASISEventMap_Impl( XMLTransformerEventMapEntry *pInit );
    ~XMLTransformerOASISEventMap_Impl();
};

XMLTransformerOASISEventMap_Impl::XMLTransformerOASISEventMap_Impl( XMLTransformerEventMapEntry *pInit )
{
    if( pInit )
    {
        XMLTransformerOASISEventMap_Impl::key_type aKey;
        XMLTransformerOASISEventMap_Impl::data_type aData;
        while( pInit->m_pOASISName )
        {
            aKey.m_nPrefix = pInit->m_nOASISPrefix;
            aKey.m_aLocalName = OUString::createFromAscii(pInit->m_pOASISName);

            OSL_ENSURE( find( aKey ) == end(), "duplicate event map entry" );

            aData = OUString::createFromAscii(pInit->m_pOOoName);

            XMLTransformerOASISEventMap_Impl::value_type aVal( aKey, aData );

            insert( aVal );
            ++pInit;
        }
    }
}

XMLTransformerOASISEventMap_Impl::~XMLTransformerOASISEventMap_Impl()
{
}

// -----------------------------------------------------------------------------

TYPEINIT1( XMLEventOASISTransformerContext, XMLRenameElemTransformerContext);

XMLEventOASISTransformerContext::XMLEventOASISTransformerContext(
        XMLTransformerBase& rImp,
        const OUString& rQName ) :
    XMLRenameElemTransformerContext( rImp, rQName,
         rImp.GetNamespaceMap().GetKeyByAttrName( rQName ), XML_EVENT )
{
}

XMLEventOASISTransformerContext::~XMLEventOASISTransformerContext()
{
}

XMLTransformerOASISEventMap_Impl
    *XMLEventOASISTransformerContext::CreateEventMap()
{
    return new XMLTransformerOASISEventMap_Impl( aTransformerEventMap );
}

XMLTransformerOASISEventMap_Impl
    *XMLEventOASISTransformerContext::CreateFormEventMap()
{
    return new XMLTransformerOASISEventMap_Impl( aFormTransformerEventMap );
}

void XMLEventOASISTransformerContext::FlushEventMap(
        XMLTransformerOASISEventMap_Impl *p )
{
    delete p;
}

OUString XMLEventOASISTransformerContext::GetEventName(
        sal_uInt16 nPrefix,
        const OUString& rName,
           XMLTransformerOASISEventMap_Impl& rMap,
           XMLTransformerOASISEventMap_Impl *pMap2)
{
    XMLTransformerOASISEventMap_Impl::key_type aKey( nPrefix, rName );
    if( pMap2 )
    {
        XMLTransformerOASISEventMap_Impl::const_iterator aIter =
            pMap2->find( aKey );
        if( !(aIter == pMap2->end()) )
            return (*aIter).second;
    }

    XMLTransformerOASISEventMap_Impl::const_iterator aIter = rMap.find( aKey );
    if( aIter == rMap.end() )
        return rName;
    else
        return (*aIter).second;
}

bool ParseURLAsString(
    const OUString& rAttrValue,
    OUString* pName, OUString* pLocation )
{
    OUString SCHEME( RTL_CONSTASCII_USTRINGPARAM( "vnd.sun.star.script:" ) );

    sal_Int32 params = rAttrValue.indexOf( '?' );
    if ( rAttrValue.indexOf( SCHEME ) != 0 || params < 0 )
    {
        return FALSE;
    }

    sal_Int32 start = SCHEME.getLength();
    *pName = rAttrValue.copy( start, params - start );

    OUString aToken;
    OUString aLanguage;
    params++;
    do
    {
        aToken = rAttrValue.getToken( 0, '&', params );
        sal_Int32 dummy = 0;

        if ( aToken.match( GetXMLToken( XML_LANGUAGE ) ) )
        {
            aLanguage = aToken.getToken( 1, '=', dummy );
        }
        else if ( aToken.match( GetXMLToken( XML_LOCATION ) ) )
        {
            OUString tmp = aToken.getToken( 1, '=', dummy );
            if ( tmp.equalsIgnoreAsciiCase( GetXMLToken( XML_DOCUMENT ) ) )
            {
                *pLocation = GetXMLToken( XML_DOCUMENT );
            }
            else
            {
                *pLocation = GetXMLToken( XML_APPLICATION );
            }
        }
    } while ( params >= 0 );

    if ( aLanguage.equalsIgnoreAsciiCaseAscii( "basic" ) )
    {
        return TRUE;
    }
    return FALSE;
}

bool ParseURL(
    const OUString& rAttrValue,
    OUString* pName, OUString* pLocation )
{
#ifdef OASIS_FILTER_OOO_1X
    return ParseURLAsString( rAttrValue, pName, pLocation );
#else
    Reference< com::sun::star::lang::XMultiServiceFactory >
        xSMgr = ::comphelper::getProcessServiceFactory();

    Reference< com::sun::star::uri::XUriReferenceFactory >
        xFactory( xSMgr->createInstance( OUString::createFromAscii(
            "com.sun.star.uri.UriReferenceFactory" ) ), UNO_QUERY );

    if ( xFactory.is() )
    {
        Reference< com::sun::star::uri::XVndSunStarScriptUrl > xUrl (
            xFactory->parse( rAttrValue ), UNO_QUERY );

        if ( xUrl.is() )
        {
            OUString aLanguageKey = GetXMLToken( XML_LANGUAGE );
            if ( xUrl.is() && xUrl->hasParameter( aLanguageKey ) )
            {
                OUString aLanguage = xUrl->getParameter( aLanguageKey );

                if ( aLanguage.equalsIgnoreAsciiCaseAscii( "basic" ) )
                {
                    *pName = xUrl->getName();

                    OUString tmp =
                        xUrl->getParameter( GetXMLToken( XML_LOCATION ) );

                    OUString doc = GetXMLToken( XML_DOCUMENT );

                    if ( tmp.equalsIgnoreAsciiCase( doc ) )
                    {
                        *pLocation = doc;
                    }
                    else
                    {
                        *pLocation = GetXMLToken( XML_APPLICATION );
                    }
                    return TRUE;
                }
            }
        }
        return FALSE;
    }
    else
    {
        return ParseURLAsString( rAttrValue, pName, pLocation );
    }
#endif
}

void XMLEventOASISTransformerContext::StartElement(
    const Reference< XAttributeList >& rAttrList )
{
    OSL_TRACE("XMLEventOASISTransformerContext::StartElement");

    XMLTransformerActions *pActions =
        GetTransformer().GetUserDefinedActions( OASIS_EVENT_ACTIONS );
    OSL_ENSURE( pActions, "go no actions" );

    Reference< XAttributeList > xAttrList( rAttrList );
    XMLMutableAttributeList *pMutableAttrList = 0;
    sal_Int16 nAttrCount = xAttrList.is() ? xAttrList->getLength() : 0;
    for( sal_Int16 i=0; i < nAttrCount; i++ )
    {
        const OUString& rAttrName = xAttrList->getNameByIndex( i );
        OUString aLocalName;
        sal_uInt16 nPrefix =
            GetTransformer().GetNamespaceMap().GetKeyByAttrName( rAttrName,
                                                                 &aLocalName );
        XMLTransformerActions::key_type aKey( nPrefix, aLocalName );
        XMLTransformerActions::const_iterator aIter =
            pActions->find( aKey );
        if( !(aIter == pActions->end() ) )
        {
            if( !pMutableAttrList )
            {
                pMutableAttrList =
                        new XMLMutableAttributeList( xAttrList );
                xAttrList = pMutableAttrList;
            }
            const OUString& rAttrValue = xAttrList->getValueByIndex( i );
            switch( (*aIter).second.m_nActionType )
            {
            case XML_ATACTION_HREF:
                {
                    OUString aAttrValue( rAttrValue );
                    OUString aName, aLocation;

                    bool bNeedsTransform =
                        ParseURL( rAttrValue, &aName, &aLocation );

                    if ( bNeedsTransform )
                    {
                        pMutableAttrList->RemoveAttributeByIndex( i );

                        OUString aAttrQName(
                            GetTransformer().GetNamespaceMap().GetQNameByKey(
                                XML_NAMESPACE_SCRIPT,
                            ::xmloff::token::GetXMLToken( XML_MACRO_NAME ) ) );

                        pMutableAttrList->AddAttribute( aAttrQName, aName );

                        sal_Int16 idx = pMutableAttrList->GetIndexByName(
                            GetTransformer().GetNamespaceMap().GetQNameByKey(
                                XML_NAMESPACE_SCRIPT,
                            GetXMLToken( XML_LANGUAGE ) ) );

                        pMutableAttrList->SetValueByIndex( idx,
                            OUString::createFromAscii("StarBasic") );

                        OUString aLocQName(
                            GetTransformer().GetNamespaceMap().GetQNameByKey(
                                XML_NAMESPACE_SCRIPT,
                                GetXMLToken( XML_LOCATION ) ) );

                        pMutableAttrList->AddAttribute( aLocQName, aLocation );
                    }
                }
                break;
            case XML_ATACTION_EVENT_NAME:
                {
                    // Check if the event belongs to a form or control by
                    // cehcking the 2nd ancestor element, f.i.:
                    // <form:button><form:event-listeners><form:event-listener>
                    const XMLTransformerContext *pObjContext =
                        GetTransformer().GetAncestorContext( 1 );
                    sal_Bool bForm = pObjContext &&

                        pObjContext->HasNamespace(XML_NAMESPACE_FORM );
                    pMutableAttrList->SetValueByIndex( i,
                                   GetTransformer().GetEventName( rAttrValue,
                                                                    bForm ) );
                }
                break;
            case XML_ATACTION_REMOVE_NAMESPACE_PREFIX:
                {
                    OUString aAttrValue( rAttrValue );
                    sal_uInt16 nValPrefix =
                        static_cast<sal_uInt16>((*aIter).second.m_nParam1);
                    if( GetTransformer().RemoveNamespacePrefix(
                                aAttrValue, nValPrefix ) )
                        pMutableAttrList->SetValueByIndex( i, aAttrValue );
                }
                break;
            case XML_ATACTION_MACRO_NAME:
            {
                OUString aName, aLocation;
                bool bNeedsTransform =
                ParseURL( rAttrValue, &aName, &aLocation );

                if ( bNeedsTransform )
                {
                    pMutableAttrList->SetValueByIndex( i, aName );

                    sal_Int16 idx = pMutableAttrList->GetIndexByName(
                    GetTransformer().GetNamespaceMap().GetQNameByKey(
                    XML_NAMESPACE_SCRIPT,
                    GetXMLToken( XML_LANGUAGE ) ) );

                    pMutableAttrList->SetValueByIndex( idx,
                    OUString::createFromAscii("StarBasic") );

                    OUString aLocQName(
                    GetTransformer().GetNamespaceMap().GetQNameByKey(
                    XML_NAMESPACE_SCRIPT,
                    GetXMLToken( XML_LOCATION ) ) );

                    pMutableAttrList->AddAttribute( aLocQName, aLocation );
                }
                else
                {
                    const OUString& rApp = GetXMLToken( XML_APPLICATION );
                    const OUString& rDoc = GetXMLToken( XML_DOCUMENT );
                    OUString aAttrValue;
                    if( rAttrValue.getLength() > rApp.getLength()+1 &&
                        rAttrValue.copy(0,rApp.getLength()).
                            equalsIgnoreAsciiCase( rApp ) &&
                        ':' == rAttrValue[rApp.getLength()] )
                    {
                        aLocation = rApp;
                        aAttrValue = rAttrValue.copy( rApp.getLength()+1 );
                    }
                    else if( rAttrValue.getLength() > rDoc.getLength()+1 &&
                             rAttrValue.copy(0,rDoc.getLength()).
                                equalsIgnoreAsciiCase( rDoc ) &&
                             ':' == rAttrValue[rDoc.getLength()] )
                    {
                        aLocation= rDoc;
                        aAttrValue = rAttrValue.copy( rDoc.getLength()+1 );
                    }
                    if( aAttrValue.getLength() )
                        pMutableAttrList->SetValueByIndex( i,
                    aAttrValue );
                    if( aLocation.getLength() )
                    {
                        OUString aAttrQName( GetTransformer().GetNamespaceMap().
                        GetQNameByKey( XML_NAMESPACE_SCRIPT,
                        ::xmloff::token::GetXMLToken( XML_LOCATION ) ) );
                        pMutableAttrList->AddAttribute( aAttrQName, aLocation );
                        // draw bug
                        aAttrQName = GetTransformer().GetNamespaceMap().
                        GetQNameByKey( XML_NAMESPACE_SCRIPT,
                        ::xmloff::token::GetXMLToken( XML_LIBRARY ) );
                        pMutableAttrList->AddAttribute( aAttrQName, aLocation );
                    }
                }
            }
            break;
            case XML_ATACTION_COPY:
                break;
            default:
                OSL_ENSURE( !this, "unknown action" );
                break;
            }
        }
    }

    XMLRenameElemTransformerContext::StartElement( xAttrList );
}
<|endoftext|>


<commit_before>#include <stdio.h>
#include "PimAction.h"
#include "PimSprite.h"
#include "PimAssert.h"

namespace Pim {
	/*
	=====================
	BaseAction::BaseAction
	=====================
	*/
	BaseAction::BaseAction(float duration) {
		done					= false;
		inQueue					= false;
		notifyOnCompletion		= false;
		queue					= NULL;
		notificationCallback	= NULL;
		dur						= duration;
		timer					= duration;
		initialDur				= duration;
	}

	/*
	=====================
	BaseAction::Cleanup
	=====================
	*/
	void BaseAction::Cleanup() {
		if (notifyOnCompletion) {
			notificationCallback->OnActionCompleted(this);
		}

		if (inQueue) {
			done = true;
			UnlistenFrame();

			queue->ActivateNext();
		} else {
			if (GetParent()) {
				GetParent()->RemoveChild(this);
			}
		}
	}

	/*
	=====================
	Action::Action
	=====================
	*/
	void Action::Activate() {
		PimAssert(GetParent() != NULL, "Action is orphan");
		ListenFrame();

		if (!notificationCallback) {
			notificationCallback = GetParent();
		}
	}

	/*
	=====================
	MoveToAction::MoveToAction
	=====================
	*/
	MoveToAction::MoveToAction(Vec2 destination, float duration)
		: Action(duration) {
		dest = destination;
	}

	/*
	=====================
	MoveToAction::Activate
	=====================
	*/
	void MoveToAction::Activate() {
		Action::Activate();
		start = GetParent()->position;
	}

	/*
	=====================
	MoveToAction::Update
	=====================
	*/
	void MoveToAction::Update(float dt) {
		ACTION_UPDATE_STATIC(
			GameNode,
			position,
			Vec2(
				dest.x + (start.x-dest.x) * (timer/dur),
				dest.y + (start.y-dest.y) * (timer/dur)
			),
			dest
		);
	}

	/*
	=====================
	MoveByAction::MoveByAction
	=====================
	*/
	MoveByAction::MoveByAction(Vec2 relative, float duration)
		: Action(duration) {
		rel		= relative;
	}

	/*
	=====================
	MoveByAction::Activate
	=====================
	*/
	void MoveByAction::Activate() {
		Action::Activate();
	}

	/*
	=====================
	MoveByAction::Update
	=====================
	*/
	void MoveByAction::Update(float dt) {
		ACTION_UPDATE_RELATIVE(GameNode, position, rel);
	}

	/*
	=====================
	RotateByAction::RotateByAction
	=====================
	*/
	RotateByAction::RotateByAction(float angle, float duration)
		: Action(duration) {
		total		= angle;
		dir			= angle / abs(angle);
	}

	/*
	=====================
	RotateByAction::Activate
	=====================
	*/
	void RotateByAction::Activate() {
		Action::Activate();
		remainding = total;
	}

	/*
	=====================
	RotateByAction::Update
	=====================
	*/
	void RotateByAction::Update(float dt) {
		ACTION_UPDATE_RELATIVE(GameNode, rotation, total);
	}

	/*
	=====================
	DelayAction::DelayAction
	=====================
	*/
	DelayAction::DelayAction(float duration)
		: Action(duration) {
	}

	/*
	=====================
	DelayAction::Activate
	=====================
	*/
	void DelayAction::Activate() {
		Action::Activate();
	}

	/*
	=====================
	DelayAction::Update
	=====================
	*/
	void DelayAction::Update(float dt) {
		timer -= dt;

		if (timer <= 0.f) {
			Cleanup();
		}
	}

	/*
	=====================
	SpriteAction::Activate
	=====================
	*/
	void SpriteAction::Activate() {
		PimAssert(GetParent() != NULL, "Action is orphan");
		PimAssert(dynamic_cast<Sprite*>(GetParent()) != NULL,
				  "Cannot add a Sprite-action to a non-sprite node!");

		ListenFrame();

		if (!notificationCallback) {
			notificationCallback = GetParent();
		}
	}

	/*
	=====================
	TintAction::TintAction
	=====================
	*/
	TintAction::TintAction(Color fadeTo, float duration)
		: SpriteAction(duration) {
		dest	= fadeTo;
	}

	/*
	=====================
	TintAction::Activate
	=====================
	*/
	void TintAction::Activate() {
		SpriteAction::Activate();
		source = ((Sprite*)GetParent())->color;
	}

	/*
	=====================
	TintAction::Update
	=====================
	*/
	void TintAction::Update(float dt) {
		ACTION_UPDATE_STATIC(
			Sprite,
			color,
			Color(
				dest.r + (source.r-dest.r) * (timer/dur),
				dest.g + (source.g-dest.g) * (timer/dur),
				dest.b + (source.b-dest.b) * (timer/dur),
				dest.a + (source.a-dest.a) * (timer/dur)
			),
			dest
		);
	}

	/*
	=====================
	ScaleToAction::ScaleToAction
	=====================
	*/
	ScaleToAction::ScaleToAction(Vec2 factor, float duration)
		: SpriteAction(duration) {
		dest = factor;
	}

	/*
	=====================
	ScaleToAction::Activate
	=====================
	*/
	void ScaleToAction::Activate() {
		SpriteAction::Activate();
		source = ((Sprite*)GetParent())->scale;
	}

	/*
	=====================
	ScaleToAction::Update
	=====================
	*/
	void ScaleToAction::Update(float dt) {
		ACTION_UPDATE_STATIC(
			Sprite,
			scale,
			Vec2(
				dest.x + (source.x-dest.x) * (timer/dur),
				dest.y + (source.y-dest.y) * (timer/dur)
			),
			dest
		);
	}

	/*
	=====================
	ScaleByAction::ScaleByAction
	=====================
	*/
	ScaleByAction::ScaleByAction(Vec2 factor, float duration)
		: SpriteAction(duration) {
		remainding = factor;
	}

	/*
	=====================
	ScaleByAction::Activate
	=====================
	*/
	void ScaleByAction::Activate() {
		SpriteAction::Activate();
	}

	/*
	=====================
	ScaleByAction::Update
	=====================
	*/
	void ScaleByAction::Update(float dt) {
		ACTION_UPDATE_RELATIVE(Sprite, scale, remainding);
	}

	/*
	=====================
	ActionQueue::ActionQueue
	=====================
	*/
	ActionQueue::ActionQueue(int numAct, BaseAction *act1, ...)
		: Action(0.f) {
		PimAssert(numAct != 0, "No actions / invalid num provided to ActionQueue");
		PimAssert(numAct < 32, "ActionQueues does not support more than 32 actions");

		curAct = NULL;

		actions.push_back(act1);
		act1->inQueue = true;
		act1->queue = this;

		va_list	argp;
		va_start(argp, act1);

		for (int i=1; i<numAct; i++) {
			actions.push_back(va_arg(argp, BaseAction*));
			actions[i]->inQueue = true;
			actions[i]->queue = this;
		}

		va_end(argp);
	}

	/*
	=====================
	ActionQueue::~ActionQueue
	=====================
	*/
	ActionQueue::~ActionQueue() {
		// Delete unplayed actions
		for (unsigned i=0; i<actions.size(); i++) {
			delete actions[i];
		}

		actions.clear();
	}

	/*
	=====================
	ActionQueue::Activate
	=====================
	*/
	void ActionQueue::Activate() {
		PimAssert(GetParent() != NULL, "Action is orphan");

		ListenFrame();
		ActivateNext();
	}

	/*
	=====================
	ActionQueue::Update
	=====================
	*/
	void ActionQueue::Update(float dt) {
		if (done) {
			GetParent()->RemoveChild(this);
		}
	}

	/*
	=====================
	ActionQueue::GetTotalTime
	=====================
	*/
	float ActionQueue::GetTotalTime() {
		float ret = 0.f;

		for (int i=0; i<actions.size(); i++) {
			ret += actions[i]->initialDur;
		}

		return ret;
	}

	/*
	=====================
	ActionQueue::ActivateNext
	=====================
	*/
	void ActionQueue::ActivateNext() {
		if (actions.size() != 0) {
			float excess = 0.f;

			if (curAct) {
				excess = curAct->timer;

				if (parent) {
					parent->RemoveChild(curAct);
				}
			}

			curAct = actions[0];
			actions.pop_front();

			curAct->dur += excess;
			curAct->timer += excess;

			if (parent) {
				parent->AddChild(curAct);
				curAct->Activate();
			}
		} else {
			curAct = NULL;
			done = true;
		}
	}

	/*
	=====================
	ActionQueueRepeat::ActionQueueRepeat
	=====================
	*/
	ActionQueueRepeat::ActionQueueRepeat(unsigned int repNum, int numAct, BaseAction *act1, ...) {
		// Code duplication from ActionQueue::ActionQueue(...).
		// Variable arguments proved difficult to pass on.
		PimAssert(numAct != 0, "No actions / invalid num provided to ActionQueue");
		PimAssert(numAct < 32, "ActionQueues does not support more than 32 actions");

		curAct = NULL;

		actions.push_back(act1);
		act1->inQueue = true;
		act1->queue = this;

		va_list	argp;
		va_start(argp, act1);

		for (int i=1; i<numAct; i++) {
			actions.push_back(va_arg(argp, BaseAction*));
			actions[i]->inQueue = true;
			actions[i]->queue = this;
		}

		va_end(argp);

		// Custom init
		actionIdx		= -1;		// gets incremented in activateNext()
		remaindingLoops = repNum;
		infinite		= false;
	}

	/*
	=====================
	ActionQueueRepeat::~ActionQueueRepeat
	=====================
	*/
	ActionQueueRepeat::~ActionQueueRepeat() {
		if (curAct) {
			// Everything in the actions-deque is deleted in ActionQueue's
			// destructor - to avoid the ActionQueue AND the parent of curAct
			// attempting to delete it, it's removed from the actions-deque.
			for (unsigned i=0; i<actions.size(); i++) {
				if (actions[i] == curAct) {
					actions.erase(actions.begin() + i);

					if (parent) {
						parent->RemoveChild(curAct);
					}
				}
			}
		}
	}

	/*
	=====================
	ActionQueueRepeat::ActivateNext
	=====================
	*/
	void ActionQueueRepeat::ActivateNext() {
		if (willDelete) return;

		// Update the action counters
		if (unsigned(++actionIdx) >= actions.size()) {
			actionIdx = 0;

			if (!infinite) {
				remaindingLoops--;
			}
		}

		if (infinite || remaindingLoops > 0) {
			float excess = 0.f;

			if (curAct) {
				excess = curAct->timer;
				float total = GetTotalTime();

				while (excess < total) {
					excess += total;
					if (!infinite) {
						remaindingLoops--;
					}
				}
				if (excess > 0.f) excess = 0.f;

				// The action is not deleted.
				if (parent) {
					GetParent()->RemoveChild(curAct, false);
				}

				curAct->UnlistenFrame();
			}

			// Prepare the next action
			curAct = actions[actionIdx];

			curAct->timer	= curAct->initialDur + excess;
			curAct->dur		= curAct->initialDur + excess;
			curAct->done	= false;

			// Run the next action
			if (parent) {
				GetParent()->AddChild(curAct);
				curAct->Activate();
			}

			curAct->Update(-excess);
		} else {
			done = true;
		}
	}
}<commit_msg>Spacing<commit_after>#include <stdio.h>
#include "PimAction.h"
#include "PimSprite.h"
#include "PimAssert.h"

namespace Pim {
	/*
	=====================
	BaseAction::BaseAction
	=====================
	*/
	BaseAction::BaseAction(float duration) {
		done					= false;
		inQueue					= false;
		notifyOnCompletion		= false;
		queue					= NULL;
		notificationCallback	= NULL;
		dur						= duration;
		timer					= duration;
		initialDur				= duration;
	}

	/*
	=====================
	BaseAction::Cleanup
	=====================
	*/
	void BaseAction::Cleanup() {
		if (notifyOnCompletion) {
			notificationCallback->OnActionCompleted(this);
		}

		if (inQueue) {
			done = true;
			UnlistenFrame();

			queue->ActivateNext();
		} else {
			if (GetParent()) {
				GetParent()->RemoveChild(this);
			}
		}
	}

	/*
	=====================
	Action::Action
	=====================
	*/
	void Action::Activate() {
		PimAssert(GetParent() != NULL, "Action is orphan");
		ListenFrame();

		if (!notificationCallback) {
			notificationCallback = GetParent();
		}
	}

	/*
	=====================
	MoveToAction::MoveToAction
	=====================
	*/
	MoveToAction::MoveToAction(Vec2 destination, float duration)
		: Action(duration) {
		dest = destination;
	}

	/*
	=====================
	MoveToAction::Activate
	=====================
	*/
	void MoveToAction::Activate() {
		Action::Activate();
		start = GetParent()->position;
	}

	/*
	=====================
	MoveToAction::Update
	=====================
	*/
	void MoveToAction::Update(float dt) {
		ACTION_UPDATE_STATIC(
			GameNode,
			position,
			Vec2(
				dest.x + (start.x-dest.x) * (timer/dur),
				dest.y + (start.y-dest.y) * (timer/dur)
			),
			dest
		);
	}

	/*
	=====================
	MoveByAction::MoveByAction
	=====================
	*/
	MoveByAction::MoveByAction(Vec2 relative, float duration)
		: Action(duration) {
		rel		= relative;
	}

	/*
	=====================
	MoveByAction::Activate
	=====================
	*/
	void MoveByAction::Activate() {
		Action::Activate();
	}

	/*
	=====================
	MoveByAction::Update
	=====================
	*/
	void MoveByAction::Update(float dt) {
		ACTION_UPDATE_RELATIVE(GameNode, position, rel);
	}

	/*
	=====================
	RotateByAction::RotateByAction
	=====================
	*/
	RotateByAction::RotateByAction(float angle, float duration)
		: Action(duration) {
		total		= angle;
		dir			= angle / abs(angle);
	}

	/*
	=====================
	RotateByAction::Activate
	=====================
	*/
	void RotateByAction::Activate() {
		Action::Activate();
		remainding = total;
	}

	/*
	=====================
	RotateByAction::Update
	=====================
	*/
	void RotateByAction::Update(float dt) {
		ACTION_UPDATE_RELATIVE(GameNode, rotation, total);
	}

	/*
	=====================
	DelayAction::DelayAction
	=====================
	*/
	DelayAction::DelayAction(float duration)
		: Action(duration) {
	}

	/*
	=====================
	DelayAction::Activate
	=====================
	*/
	void DelayAction::Activate() {
		Action::Activate();
	}

	/*
	=====================
	DelayAction::Update
	=====================
	*/
	void DelayAction::Update(float dt) {
		timer -= dt;

		if (timer <= 0.f) {
			Cleanup();
		}
	}

	/*
	=====================
	SpriteAction::Activate
	=====================
	*/
	void SpriteAction::Activate() {
		PimAssert(GetParent() != NULL, "Action is orphan");
		PimAssert(dynamic_cast<Sprite*>(GetParent()) != NULL,
				  "Cannot add a Sprite-action to a non-sprite node!");

		ListenFrame();

		if (!notificationCallback) {
			notificationCallback = GetParent();
		}
	}

	/*
	=====================
	TintAction::TintAction
	=====================
	*/
	TintAction::TintAction(Color fadeTo, float duration)
		: SpriteAction(duration) {
		dest	= fadeTo;
	}

	/*
	=====================
	TintAction::Activate
	=====================
	*/
	void TintAction::Activate() {
		SpriteAction::Activate();
		source = ((Sprite*)GetParent())->color;
	}

	/*
	=====================
	TintAction::Update
	=====================
	*/
	void TintAction::Update(float dt) {
		ACTION_UPDATE_STATIC(
			Sprite,
			color,
			Color(
				dest.r + (source.r-dest.r) * (timer/dur),
				dest.g + (source.g-dest.g) * (timer/dur),
				dest.b + (source.b-dest.b) * (timer/dur),
				dest.a + (source.a-dest.a) * (timer/dur)
			),
			dest
		);
	}

	/*
	=====================
	ScaleToAction::ScaleToAction
	=====================
	*/
	ScaleToAction::ScaleToAction(Vec2 factor, float duration)
		: SpriteAction(duration) {
		dest = factor;
	}

	/*
	=====================
	ScaleToAction::Activate
	=====================
	*/
	void ScaleToAction::Activate() {
		SpriteAction::Activate();
		source = ((Sprite*)GetParent())->scale;
	}

	/*
	=====================
	ScaleToAction::Update
	=====================
	*/
	void ScaleToAction::Update(float dt) {
		ACTION_UPDATE_STATIC(
			Sprite,
			scale,
			Vec2(
				dest.x + (source.x-dest.x) * (timer/dur),
				dest.y + (source.y-dest.y) * (timer/dur)
			),
			dest
		);
	}

	/*
	=====================
	ScaleByAction::ScaleByAction
	=====================
	*/
	ScaleByAction::ScaleByAction(Vec2 factor, float duration)
		: SpriteAction(duration) {
		remainding = factor;
	}

	/*
	=====================
	ScaleByAction::Activate
	=====================
	*/
	void ScaleByAction::Activate() {
		SpriteAction::Activate();
	}

	/*
	=====================
	ScaleByAction::Update
	=====================
	*/
	void ScaleByAction::Update(float dt) {
		ACTION_UPDATE_RELATIVE(Sprite, scale, remainding);
	}

	/*
	=====================
	ActionQueue::ActionQueue
	=====================
	*/
	ActionQueue::ActionQueue(int numAct, BaseAction *act1, ...)
		: Action(0.f) {
		PimAssert(numAct != 0, "No actions / invalid num provided to ActionQueue");
		PimAssert(numAct < 32, "ActionQueues does not support more than 32 actions");

		curAct = NULL;

		actions.push_back(act1);
		act1->inQueue = true;
		act1->queue = this;

		va_list	argp;
		va_start(argp, act1);

		for (int i=1; i<numAct; i++) {
			actions.push_back(va_arg(argp, BaseAction*));
			actions[i]->inQueue = true;
			actions[i]->queue = this;
		}

		va_end(argp);
	}

	/*
	=====================
	ActionQueue::~ActionQueue
	=====================
	*/
	ActionQueue::~ActionQueue() {
		// Delete unplayed actions
		for (unsigned i=0; i<actions.size(); i++) {
			delete actions[i];
		}

		actions.clear();
	}

	/*
	=====================
	ActionQueue::Activate
	=====================
	*/
	void ActionQueue::Activate() {
		PimAssert(GetParent() != NULL, "Action is orphan");

		ListenFrame();
		ActivateNext();
	}

	/*
	=====================
	ActionQueue::Update
	=====================
	*/
	void ActionQueue::Update(float dt) {
		if (done) {
			GetParent()->RemoveChild(this);
		}
	}

	/*
	=====================
	ActionQueue::GetTotalTime
	=====================
	*/
	float ActionQueue::GetTotalTime() {
		float ret = 0.f;

		for (int i=0; i<actions.size(); i++) {
			ret += actions[i]->initialDur;
		}

		return ret;
	}

	/*
	=====================
	ActionQueue::ActivateNext
	=====================
	*/
	void ActionQueue::ActivateNext() {
		if (actions.size() != 0) {
			float excess = 0.f;

			if (curAct) {
				excess = curAct->timer;

				if (parent) {
					parent->RemoveChild(curAct);
				}
			}

			curAct = actions[0];
			actions.pop_front();

			curAct->dur += excess;
			curAct->timer += excess;

			if (parent) {
				parent->AddChild(curAct);
				curAct->Activate();
			}
		} else {
			curAct = NULL;
			done = true;
		}
	}

	/*
	=====================
	ActionQueueRepeat::ActionQueueRepeat
	=====================
	*/
	ActionQueueRepeat::ActionQueueRepeat(unsigned int repNum, int numAct, BaseAction *act1, ...) {
		// Code duplication from ActionQueue::ActionQueue(...).
		// Variable arguments proved difficult to pass on.
		PimAssert(numAct != 0, "No actions / invalid num provided to ActionQueue");
		PimAssert(numAct < 32, "ActionQueues does not support more than 32 actions");

		curAct = NULL;

		actions.push_back(act1);
		act1->inQueue = true;
		act1->queue = this;

		va_list	argp;
		va_start(argp, act1);

		for (int i=1; i<numAct; i++) {
			actions.push_back(va_arg(argp, BaseAction*));
			actions[i]->inQueue = true;
			actions[i]->queue = this;
		}

		va_end(argp);

		// Custom init
		actionIdx		= -1;		// gets incremented in activateNext()
		remaindingLoops = repNum;
		infinite		= false;
	}

	/*
	=====================
	ActionQueueRepeat::~ActionQueueRepeat
	=====================
	*/
	ActionQueueRepeat::~ActionQueueRepeat() {
		if (curAct) {
			// Everything in the actions-deque is deleted in ActionQueue's
			// destructor - to avoid the ActionQueue AND the parent of curAct
			// attempting to delete it, it's removed from the actions-deque.
			for (unsigned i=0; i<actions.size(); i++) {
				if (actions[i] == curAct) {
					actions.erase(actions.begin() + i);

					if (parent) {
						parent->RemoveChild(curAct);
					}
				}
			}
		}
	}

	/*
	=====================
	ActionQueueRepeat::ActivateNext
	=====================
	*/
	void ActionQueueRepeat::ActivateNext() {
		if (willDelete) return;

		// Update the action counters
		if (unsigned(++actionIdx) >= actions.size()) {
			actionIdx = 0;

			if (!infinite) {
				remaindingLoops--;
			}
		}

		if (infinite || remaindingLoops > 0) {
			float excess = 0.f;

			if (curAct) {
				excess = curAct->timer;
				float total = GetTotalTime();

				while (excess < total) {
					excess += total;
					if (!infinite) {
						remaindingLoops--;
					}
				}
				if (excess > 0.f) excess = 0.f;

				// The action is not deleted.
				if (parent) {
					GetParent()->RemoveChild(curAct, false);
				}

				curAct->UnlistenFrame();
			}

			// Prepare the next action
			curAct = actions[actionIdx];

			curAct->timer	= curAct->initialDur + excess;
			curAct->dur		= curAct->initialDur + excess;
			curAct->done	= false;

			// Run the next action
			if (parent) {
				GetParent()->AddChild(curAct);
				curAct->Activate();
			}

			curAct->Update(-excess);
		} else {
			done = true;
		}
	}
}<|endoftext|>