<commit_before>/* IBM_PROLOG_BEGIN_TAG                                                   */
/* This is an automatically generated prolog.                             */
/*                                                                        */
/* $Source: src/usr/diag/prdf/plat/mem/prdfMemChnlFailCache.H $           */
/*                                                                        */
/* OpenPOWER HostBoot Project                                             */
/*                                                                        */
/* Contributors Listed Below - COPYRIGHT 2018,2019                        */
/* [+] International Business Machines Corp.                              */
/*                                                                        */
/*                                                                        */
/* Licensed under the Apache License, Version 2.0 (the "License");        */
/* you may not use this file except in compliance with the License.       */
/* You may obtain a copy of the License at                                */
/*                                                                        */
/*     http://www.apache.org/licenses/LICENSE-2.0                         */
/*                                                                        */
/* Unless required by applicable law or agreed to in writing, software    */
/* distributed under the License is distributed on an "AS IS" BASIS,      */
/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or        */
/* implied. See the License for the specific language governing           */
/* permissions and limitations under the License.                         */
/*                                                                        */
/* IBM_PROLOG_END_TAG                                                     */
#include <map>
#include <targeting/common/targetservice.H>

#ifndef __prdfMemChnlFailCache_H
#define __prdfMemChnlFailCache_H

namespace PRDF
{

typedef std::map<TARGETING::TYPE, std::vector<uint64_t>> TargetScoms_t;

TargetScoms_t chnlFailScomList =
{
    {
        TARGETING::TYPE_MEMBUF,
        { // SCOMs
            0x500F001C, // GLOBAL_CS_FIR
            0x500F001B, // GLOBAL_RE_FIR
            0x500F001A, // GLOBAL_SPA_FIR
            0x01040000, // TP_CHIPLET_CS_FIR
            0x01040001, // TP_CHIPLET_RE_FIR
            0x01040002, // TP_CHIPLET_FIR_MASK
            0x0104000A, // TP_LFIR
            0x0104000D, // TP_LFIR_MASK
            0x01040010, // TP_LFIR_ACT0
            0x01040011, // TP_LFIR_ACT1
            0x02040000, // NEST_CHIPLET_CS_FIR
            0x02040001, // NEST_CHIPLET_RE_FIR
            0x02040002, // NEST_CHIPLET_FIR_MASK
            0x0204000A, // NEST_LFIR
            0x0204000D, // NEST_LFIR_MASK
            0x02040010, // NEST_LFIR_ACT0
            0x02040011, // NEST_LFIR_ACT1
            0x02010400, // DMIFIR
            0x02010403, // DMIFIR_MASK
            0x02010406, // DMIFIR_ACT0
            0x02010407, // DMIFIR_ACT1
            0x02010800, // MBIFIR
            0x02010803, // MBIFIR_MASK
            0x02010806, // MBIFIR_ACT0
            0x02010807, // MBIFIR_ACT1
            0x02011400, // MBSFIR
            0x02011403, // MBSFIR_MASK
            0x02011406, // MBSFIR_ACT0
            0x02011407, // MBSFIR_ACT1
            0x0201141e, // MBSSECUREFIR
            0x02011440, // MBSECCFIR_0
            0x02011443, // MBSECCFIR_0_MASK
            0x02011446, // MBSECCFIR_0_ACT0
            0x02011447, // MBSECCFIR_0_ACT1
            0x02011480, // MBSECCFIR_1
            0x02011483, // MBSECCFIR_1_MASK
            0x02011486, // MBSECCFIR_1_ACT0
            0x02011487, // MBSECCFIR_1_ACT1
            0x020115c0, // SCACFIR
            0x020115c3, // SCACFIR_MASK
            0x020115c6, // SCACFIR_ACT0
            0x020115c7, // SCACFIR_ACT1
            0x02011600, // MCBISTFIR_0
            0x02011603, // MCBISTFIR_0_MASK
            0x02011606, // MCBISTFIR_0_ACT0
            0x02011607, // MCBISTFIR_0_ACT1
            0x02011700, // MCBISTFIR_1
            0x02011703, // MCBISTFIR_1_MASK
            0x02011706, // MCBISTFIR_1_ACT0
            0x02011707, // MCBISTFIR_1_ACT1
            0x03040000, // MEM_CHIPLET_CS_FIR
            0x03040001, // MEM_CHIPLET_RE_FIR
            0x03040002, // MEM_CHIPLET_FIR_MASK
            0x03040004, // MEM_CHIPLET_SPA_FIR
            0x03040007, // MEM_CHIPLET_SPA_FIR_MASK
            0x0304000A, // MEM_LFIR
            0x0304000D, // MEM_LFIR_MASK
            0x03040010, // MEM_LFIR_ACT0
            0x03040011, // MEM_LFIR_ACT1
            0x01030009, // TP_ERROR_STATUS
            0x02030009, // NEST_ERROR_STATUS
            0x0201080F, // MBIERPT
            0x02011413, // MBSCERR1
            0x0201142C, // MBSCERR2
            0x02011466, // MBA0_MBSECCERRPT_0
            0x02011467, // MBA0_MBSECCERRPT_1
            0x020114A6, // MBA1_MBSECCERRPT_0
            0x020114A7, // MBA1_MBSECCERRPT_1
            0x0201168f, // MBA0_MBXERRSTAT
            0x0201178f, // MBA1_MBXERRSTAT
            0x020115D4, // SENSORCACHEERRPT
            0x03030009, // MEM_ERROR_STATUS
        }
    },
    {
        TARGETING::TYPE_MBA,
        {
            0x03010400, // MBACALFIR
            0x03010403, // MBACALFIR_MASK
            0x03010406, // MBACALFIR_ACT0
            0x03010407, // MBACALFIR_ACT1
            0x0301041b, // MBASECUREFIR
            0x03010600, // MBAFIR
            0x03010603, // MBAFIR_MASK
            0x03010606, // MBAFIR_ACT0
            0x03010607, // MBAFIR_ACT1
            0x03010611, // MBASPA
            0x03010614, // MBASPA_MASK
            0x0301041A, // MBA_ERR_REPORT
            0x030106E7, // MBA_MCBERRPTQ
            0x800200900301143F, // MBADDRPHYFIR
            0x800200930301143F, // MBADDRPHYFIR_MASK
            0x800200960301143F, // MBADDRPHYFIR_ACT0
            0x800200970301143F, // MBADDRPHYFIR_ACT1
            0x8000D0060301143F, // DDRPHY_APB_FIR_ERR0_P0
            0x8000D0070301143F, // DDRPHY_APB_FIR_ERR1_P0
            0x8001D0060301143F, // DDRPHY_APB_FIR_ERR0_P1
            0x8001D0070301143F, // DDRPHY_APB_FIR_ERR1_P1
        }
    }
};

} // namespace PRDF

#endif // __prdfMemChnlFailCache_H
<commit_msg>PRD: Update reg list in prdfMemChnlFailCache.H<commit_after>/* IBM_PROLOG_BEGIN_TAG                                                   */
/* This is an automatically generated prolog.                             */
/*                                                                        */
/* $Source: src/usr/diag/prdf/plat/mem/prdfMemChnlFailCache.H $           */
/*                                                                        */
/* OpenPOWER HostBoot Project                                             */
/*                                                                        */
/* Contributors Listed Below - COPYRIGHT 2018,2020                        */
/* [+] International Business Machines Corp.                              */
/*                                                                        */
/*                                                                        */
/* Licensed under the Apache License, Version 2.0 (the "License");        */
/* you may not use this file except in compliance with the License.       */
/* You may obtain a copy of the License at                                */
/*                                                                        */
/*     http://www.apache.org/licenses/LICENSE-2.0                         */
/*                                                                        */
/* Unless required by applicable law or agreed to in writing, software    */
/* distributed under the License is distributed on an "AS IS" BASIS,      */
/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or        */
/* implied. See the License for the specific language governing           */
/* permissions and limitations under the License.                         */
/*                                                                        */
/* IBM_PROLOG_END_TAG                                                     */
#include <map>
#include <targeting/common/targetservice.H>

#ifndef __prdfMemChnlFailCache_H
#define __prdfMemChnlFailCache_H

namespace PRDF
{

typedef std::map<TARGETING::TYPE, std::vector<uint64_t>> TargetScoms_t;

TargetScoms_t chnlFailScomList =
{
    {
        TARGETING::TYPE_OCMB_CHIP,
        { // SCOMs
            0x08040000, // OCMB_CHIPLET_CS_FIR
            0x08040001, // OCMB_CHIPLET_RE_FIR
            0x08040002, // OCMB_CHIPLET_FIR_MASK
            0x08040004, // OCMB_CHIPLET_SPA_FIR
            0x08040007, // OCMB_CHIPLET_SPA_FIR_MASK
            0x0804000a, // OCMB_LFIR
            0x0804000d, // OCMB_LFIR_MASK
            0x08040010, // OCMB_LFIR_ACT0
            0x08040011, // OCMB_LFIR_ACT1
            0x08010870, // MMIOFIR
            0x08010873, // MMIOFIR_MASK
            0x08010876, // MMIOFIR_ACT0
            0x08010877, // MMIOFIR_ACT1
            0x08011400, // SRQFIR
            0x08011403, // SRQFIR_MASK
            0x08011406, // SRQFIR_ACT0
            0x08011407, // SRQFIR_ACT1
            0x08011800, // MCBISTFIR
            0x08011803, // MCBISTFIR_MASK
            0x08011806, // MCBISTFIR_ACT0
            0x08011807, // MCBISTFIR_ACT1
            0x08011c00, // RDFFIR
            0x08011c03, // RDFFIR_MASK
            0x08011c06, // RDFFIR_ACT0
            0x08011c07, // RDFFIR_ACT1
            0x08012400, // TLXFIR
            0x08012403, // TLXFIR_MASK
            0x08012406, // TLXFIR_ACT0
            0x08012407, // TLXFIR_ACT1
            0x08012800, // OMIDLFIR
            0x08012803, // OMIDLFIR_MASK
            0x08012806, // OMIDLFIR_ACT0
            0x08012807, // OMIDLFIR_ACT1
            0x08011858, // OCMB_MBSSYMEC0
            0x08011859, // OCMB_MBSSYMEC1
            0x0801185A, // OCMB_MBSSYMEC2
            0x0801185B, // OCMB_MBSSYMEC3
            0x0801185C, // OCMB_MBSSYMEC4
            0x0801185D, // OCMB_MBSSYMEC5
            0x0801185E, // OCMB_MBSSYMEC6
            0x0801185F, // OCMB_MBSSYMEC7
            0x08011860, // OCMB_MBSSYMEC8
            0x0801187E, // MBSEVR0
            0x08011855, // MBSEC0
            0x08011856, // MBSEC1
            0x08011869, // MBSMSEC
            0x08011857, // MBSTR
            0x080118D6, // MCBAGRA
            0x080118D7, // MCBMCAT
            0x080118DB, // MCB_CNTL
            0x080118DC, // MCB_CNTLSTAT
            0x08011C10, // HW_MS0
            0x08011C11, // HW_MS1
            0x08011C12, // HW_MS2
            0x08011C13, // HW_MS3
            0x08011C14, // HW_MS4
            0x08011C15, // HW_MS5
            0x08011C16, // HW_MS6
            0x08011C17, // HW_MS7
            0x08011C18, // FW_MS0
            0x08011C19, // FW_MS1
            0x08011C1A, // FW_MS2
            0x08011C1B, // FW_MS3
            0x08011C1C, // FW_MS4
            0x08011C1D, // FW_MS5
            0x08011C1E, // FW_MS6
            0x08011C1F, // FW_MS7
            0x0801241C, // TLX_ERR0_REPORT
            0x0801241D, // TLX_ERR1_REPORT
            0x08012414, // TLX_ERR0_REPORT_MASK
            0x08012415, // TLX_ERR1_REPORT_MASK
            0x0801186A, // MBNCER
            0x0801186B, // MBRCER
            0x0801186C, // MBMPER
            0x0801186D, // MBUER
            0x0801186E, // MBAUER
            0x08011415, // FARB0
            0x08011C0C, // EXP_MSR
            0x0801186F, // MC_ADDR_TRANS
            0x08011870, // MC_ADDR_TRANS1
            0x08011871, // MC_ADDR_TRANS2
        }
    }
};

} // namespace PRDF

#endif // __prdfMemChnlFailCache_H
<|endoftext|>


<commit_before>/*
 * The Apache Software License, Version 1.1
 *
 *
 * Copyright (c) 2001 The Apache Software Foundation.  All rights
 * reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 *
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in
 *    the documentation and/or other materials provided with the
 *    distribution.
 *
 * 3. The end-user documentation included with the redistribution,
 *    if any, must include the following acknowledgment:
 *       "This product includes software developed by the
 *        Apache Software Foundation (http://www.apache.org/)."
 *    Alternately, this acknowledgment may appear in the software itself,
 *    if and wherever such third-party acknowledgments normally appear.
 *
 * 4. The names "Xerces" and "Apache Software Foundation" must
 *    not be used to endorse or promote products derived from this
 *    software without prior written permission. For written
 *    permission, please contact apache@apache.org.
 *
 * 5. Products derived from this software may not be called "Apache",
 *    nor may "Apache" appear in their name, without prior written
 *    permission of the Apache Software Foundation.
 *
 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED 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 APACHE SOFTWARE FOUNDATION OR
 * ITS 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.
 * ====================================================================
 *
 * This software consists of voluntary contributions made by many
 * individuals on behalf of the Apache Software Foundation and was
 * originally based on software copyright (c) 2001, International
 * Business Machines, Inc., http://www.apache.org.  For more
 * information on the Apache Software Foundation, please see
 * <http://www.apache.org/>.
 */

/**
 * $Id$
 */

#if !defined(GRAMMARRESOLVER_HPP)
#define GRAMMARRESOLVER_HPP

#include <xercesc/util/RefHashTableOf.hpp>
#include <xercesc/util/StringPool.hpp>
#include <xercesc/validators/common/Grammar.hpp>

XERCES_CPP_NAMESPACE_BEGIN

class DatatypeValidator;
class DatatypeValidatorFactory;
class XMLGrammarPool;
class XMLGrammarDescription;
class GrammarEntry;

/**
 * This class embodies the representation of a Grammar pool Resolver.
 * This class is called from the validator.
 *
 */

class VALIDATORS_EXPORT GrammarResolver : public XMemory
{
public:

    /** @name Constructor and Destructor */
    //@{
    /**
     *
     * Default Constructor
     */
    GrammarResolver(
                    XMLGrammarPool* const gramPool
                  , MemoryManager*  const manager = XMLPlatformUtils::fgMemoryManager
                    );
    /**
      * Destructor
      */
    ~GrammarResolver();

    //@}

    /** @name Getter methods */
    //@{
    /**
     * Retrieve the DatatypeValidator
     *
     * @param uriStr the namespace URI
     * @param typeName the type name
     * @return the DatatypeValidator associated with namespace & type name
     */
    DatatypeValidator* getDatatypeValidator(const XMLCh* const uriStr,
                                            const XMLCh* const typeName);

    /**
     * Retrieve the grammar that is associated with the specified namespace key
     *
     * @param  gramDesc   Namespace key into Grammar pool
     * @return Grammar abstraction associated with the NameSpace key.
     */
    Grammar* getGrammar( XMLGrammarDescription* const gramDesc ) ;

    /**
     * Get an enumeration of Grammar in the Grammar pool
     *
     * @return enumeration of Grammar in Grammar pool
     */
    RefHashTableOfEnumerator<GrammarEntry> getGrammarEnumerator() const;

    /**
     * Get a string pool of schema grammar element/attribute names/prefixes
     * (used by TraverseSchema)
     *
     * @return a string pool of schema grammar element/attribute names/prefixes
     */
    XMLStringPool* getStringPool();

    /**
     * Is the specified Namespace key in Grammar pool?
     *
     * @param  nameSpaceKey    Namespace key
     * @return True if Namespace key association is in the Grammar pool.
     */
    bool containsNameSpace( const XMLCh* const nameSpaceKey );

    inline XMLGrammarPool* const getGrammarPool() const;

    //@}

    /** @name Setter methods */
    //@{

    /**
      * Set the 'Grammar caching' flag
      */
    void cacheGrammarFromParse(const bool newState);

    /**
      * Set the 'Use cached grammar' flag
      */
    void useCachedGrammarInParse(const bool newState);

    //@}

    /** @name GrammarResolver methods */
    //@{
    /**
     * Add the Grammar with Namespace Key associated to the Grammar Pool.
     * The Grammar will be owned by the Grammar Pool.
     *
     * @param  gramDesc        Key to associate with Grammar abstraction
     * @param  grammarToAdopt  Grammar abstraction used by validator.
     */
    void putGrammar(XMLGrammarDescription* const gramDesc
                  , Grammar* const               grammarToAdopt );

    /**
     * Returns the Grammar with Namespace Key associated from the Grammar Pool
     * The Key entry is removed from the table (grammar is not deleted if
     * adopted - now owned by caller).
     *
     * @param  gramDesc    Key to associate with Grammar abstraction
     */
    Grammar* orphanGrammar(XMLGrammarDescription* const gramDesc);

    /**
     * Cache the grammars in fGrammarBucket to fCachedGrammarRegistry.
     * If a grammar with the same key is already cached, an exception is
     * thrown and none of the grammars will be cached.
     */
    void cacheGrammars();

    /**
     * Reset internal Namespace/Grammar registry.
     */
    void reset();
    void resetCachedGrammar();

    //@}

private:

    XMLGrammarDescription* getGrammarDescription(const XMLCh* const);

    // -----------------------------------------------------------------------
    //  Private data members
    //
    //  fStringPool            The string pool used by TraverseSchema to store
    //                         element/attribute names and prefixes.
    //
    //  fGrammarBucket       The parsed Grammar Pool, if no caching option.
    //
    //  fCachedGrammarRegistry The cached Grammar Pool.  It represents a
    //                         mapping between Namespace and a Grammar
    //
    //  fDataTypeReg           DatatypeValidatorFactory registery
    //
    //  fMemoryManager         Pluggable memory manager for dynamic memory
    //                         allocation/deallocation
    // -----------------------------------------------------------------------
    bool                       fCacheGrammar;
    bool                       fUseCachedGrammar;
    bool                       fGrammarPoolFromExternalApplication;
    XMLStringPool              fStringPool;
    RefHashTableOf<GrammarEntry>*   fGrammarBucket;
    DatatypeValidatorFactory*  fDataTypeReg;
    MemoryManager*             fMemoryManager;
    XMLGrammarPool*            fGrammarPool;
};

inline XMLStringPool* GrammarResolver::getStringPool() {

    return &fStringPool;
}

inline void GrammarResolver::useCachedGrammarInParse(const bool aValue)
{
    fUseCachedGrammar = aValue;
}

inline XMLGrammarPool* const GrammarResolver::getGrammarPool() const
{
    return fGrammarPool;
}

XERCES_CPP_NAMESPACE_END

#endif
<commit_msg>Stateless Grammar: getGrammarPoolMemoryManager()<commit_after>/*
 * The Apache Software License, Version 1.1
 *
 *
 * Copyright (c) 2001 The Apache Software Foundation.  All rights
 * reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 *
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in
 *    the documentation and/or other materials provided with the
 *    distribution.
 *
 * 3. The end-user documentation included with the redistribution,
 *    if any, must include the following acknowledgment:
 *       "This product includes software developed by the
 *        Apache Software Foundation (http://www.apache.org/)."
 *    Alternately, this acknowledgment may appear in the software itself,
 *    if and wherever such third-party acknowledgments normally appear.
 *
 * 4. The names "Xerces" and "Apache Software Foundation" must
 *    not be used to endorse or promote products derived from this
 *    software without prior written permission. For written
 *    permission, please contact apache@apache.org.
 *
 * 5. Products derived from this software may not be called "Apache",
 *    nor may "Apache" appear in their name, without prior written
 *    permission of the Apache Software Foundation.
 *
 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED 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 APACHE SOFTWARE FOUNDATION OR
 * ITS 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.
 * ====================================================================
 *
 * This software consists of voluntary contributions made by many
 * individuals on behalf of the Apache Software Foundation and was
 * originally based on software copyright (c) 2001, International
 * Business Machines, Inc., http://www.apache.org.  For more
 * information on the Apache Software Foundation, please see
 * <http://www.apache.org/>.
 */

/**
 * $Id$
 */

#if !defined(GRAMMARRESOLVER_HPP)
#define GRAMMARRESOLVER_HPP

#include <xercesc/framework/XMLGrammarPool.hpp>
#include <xercesc/util/RefHashTableOf.hpp>
#include <xercesc/util/StringPool.hpp>
#include <xercesc/validators/common/Grammar.hpp>

XERCES_CPP_NAMESPACE_BEGIN

class DatatypeValidator;
class DatatypeValidatorFactory;
class XMLGrammarDescription;
class GrammarEntry;

/**
 * This class embodies the representation of a Grammar pool Resolver.
 * This class is called from the validator.
 *
 */

class VALIDATORS_EXPORT GrammarResolver : public XMemory
{
public:

    /** @name Constructor and Destructor */
    //@{
    /**
     *
     * Default Constructor
     */
    GrammarResolver(
                    XMLGrammarPool* const gramPool
                  , MemoryManager*  const manager = XMLPlatformUtils::fgMemoryManager
                    );
    /**
      * Destructor
      */
    ~GrammarResolver();

    //@}

    /** @name Getter methods */
    //@{
    /**
     * Retrieve the DatatypeValidator
     *
     * @param uriStr the namespace URI
     * @param typeName the type name
     * @return the DatatypeValidator associated with namespace & type name
     */
    DatatypeValidator* getDatatypeValidator(const XMLCh* const uriStr,
                                            const XMLCh* const typeName);

    /**
     * Retrieve the grammar that is associated with the specified namespace key
     *
     * @param  gramDesc   Namespace key into Grammar pool
     * @return Grammar abstraction associated with the NameSpace key.
     */
    Grammar* getGrammar( XMLGrammarDescription* const gramDesc ) ;

    /**
     * Get an enumeration of Grammar in the Grammar pool
     *
     * @return enumeration of Grammar in Grammar pool
     */
    RefHashTableOfEnumerator<GrammarEntry> getGrammarEnumerator() const;

    /**
     * Get a string pool of schema grammar element/attribute names/prefixes
     * (used by TraverseSchema)
     *
     * @return a string pool of schema grammar element/attribute names/prefixes
     */
    XMLStringPool* getStringPool();

    /**
     * Is the specified Namespace key in Grammar pool?
     *
     * @param  nameSpaceKey    Namespace key
     * @return True if Namespace key association is in the Grammar pool.
     */
    bool containsNameSpace( const XMLCh* const nameSpaceKey );

    inline XMLGrammarPool* const getGrammarPool() const;

    inline MemoryManager* const getGrammarPoolMemoryManager() const;

    //@}

    /** @name Setter methods */
    //@{

    /**
      * Set the 'Grammar caching' flag
      */
    void cacheGrammarFromParse(const bool newState);

    /**
      * Set the 'Use cached grammar' flag
      */
    void useCachedGrammarInParse(const bool newState);

    //@}

    /** @name GrammarResolver methods */
    //@{
    /**
     * Add the Grammar with Namespace Key associated to the Grammar Pool.
     * The Grammar will be owned by the Grammar Pool.
     *
     * @param  gramDesc        Key to associate with Grammar abstraction
     * @param  grammarToAdopt  Grammar abstraction used by validator.
     */
    void putGrammar(XMLGrammarDescription* const gramDesc
                  , Grammar* const               grammarToAdopt );

    /**
     * Returns the Grammar with Namespace Key associated from the Grammar Pool
     * The Key entry is removed from the table (grammar is not deleted if
     * adopted - now owned by caller).
     *
     * @param  gramDesc    Key to associate with Grammar abstraction
     */
    Grammar* orphanGrammar(XMLGrammarDescription* const gramDesc);

    /**
     * Cache the grammars in fGrammarBucket to fCachedGrammarRegistry.
     * If a grammar with the same key is already cached, an exception is
     * thrown and none of the grammars will be cached.
     */
    void cacheGrammars();

    /**
     * Reset internal Namespace/Grammar registry.
     */
    void reset();
    void resetCachedGrammar();

    //@}

private:

    XMLGrammarDescription* getGrammarDescription(const XMLCh* const);

    // -----------------------------------------------------------------------
    //  Private data members
    //
    //  fStringPool            The string pool used by TraverseSchema to store
    //                         element/attribute names and prefixes.
    //
    //  fGrammarBucket       The parsed Grammar Pool, if no caching option.
    //
    //  fCachedGrammarRegistry The cached Grammar Pool.  It represents a
    //                         mapping between Namespace and a Grammar
    //
    //  fDataTypeReg           DatatypeValidatorFactory registery
    //
    //  fMemoryManager         Pluggable memory manager for dynamic memory
    //                         allocation/deallocation
    // -----------------------------------------------------------------------
    bool                       fCacheGrammar;
    bool                       fUseCachedGrammar;
    bool                       fGrammarPoolFromExternalApplication;
    XMLStringPool              fStringPool;
    RefHashTableOf<GrammarEntry>*   fGrammarBucket;
    DatatypeValidatorFactory*  fDataTypeReg;
    MemoryManager*             fMemoryManager;
    XMLGrammarPool*            fGrammarPool;
};

inline XMLStringPool* GrammarResolver::getStringPool() {

    return &fStringPool;
}

inline void GrammarResolver::useCachedGrammarInParse(const bool aValue)
{
    fUseCachedGrammar = aValue;
}

inline XMLGrammarPool* const GrammarResolver::getGrammarPool() const
{
    return fGrammarPool;
}

inline MemoryManager* const GrammarResolver::getGrammarPoolMemoryManager() const
{
    return fGrammarPool->getMemoryManager();
}

XERCES_CPP_NAMESPACE_END

#endif
<|endoftext|>


<commit_before>/*
 * V1.cpp
 *
 *  Created on: Jul 30, 2008
 *      Author: rasmussn
 */

#include "../include/pv_common.h"
#include "../include/default_params.h"
#include "../connections/PVConnection.h"
#include "HyPerLayer.hpp"
#include "V1.hpp"

#include <assert.h>
#include <float.h>
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

namespace PV
{

V1Params V1DefaultParams =
{
    V_REST, V_EXC, V_INH, V_INHB,            // V (mV)
    TAU_VMEM, TAU_EXC, TAU_INH, TAU_INHB,
    VTH_REST,  TAU_VTH, DELTA_VTH, DELTA_VTH_DECAY,	     // tau (ms)
    250, NOISE_AMP*( 1.0/TAU_EXC ) * ( ( TAU_INH * (V_REST-V_INH) + TAU_INHB * (V_REST-V_INHB) ) / (V_EXC-V_REST) ),
    250, NOISE_AMP*1.0,
    250, NOISE_AMP*1.0                       // noise (G)
};

V1::V1(const char* name, HyPerCol * hc)
{
   initialize(name, hc, TypeV1Simple);
}

V1::V1(const char* name, HyPerCol * hc, PVLayerType type)
{
   initialize(name, hc, type);
}

void V1::initialize(const char* name, HyPerCol * hc, PVLayerType type)
{
   setParent(hc);
   init(name, type);

   setParams(parent->parameters(), &V1DefaultParams);
   pvlayer_setFuncs(clayer, (INIT_FN) &LIF2_init, (UPDATE_FN) &LIF2_update_exact_linear);

   hc->addLayer(this);
}

int V1::setParams(PVParams * params, V1Params * p)
{
   const char * name = getName();
   float dt = .001 * parent->getDeltaTime();  // seconds

   clayer->params = (float *) malloc(sizeof(*p));
   memcpy(clayer->params, p, sizeof(*p));

   clayer->numParams = sizeof(*p) / sizeof(float);
   assert(clayer->numParams == 18);

   V1Params * cp = (V1Params *) clayer->params;

   if (params->present(name, "Vrest")) cp->Vrest = params->value(name, "Vrest");
   if (params->present(name, "Vexc"))  cp->Vexc  = params->value(name, "Vexc");
   if (params->present(name, "Vinh"))  cp->Vinh  = params->value(name, "Vinh");
   if (params->present(name, "VinhB")) cp->VinhB = params->value(name, "VinhB");

   if (params->present(name, "tau"))   cp->tau   = params->value(name, "tau");
   if (params->present(name, "tauE"))  cp->tauE  = params->value(name, "tauE");
   if (params->present(name, "tauI"))  cp->tauI  = params->value(name, "tauI");
   if (params->present(name, "tauIB")) cp->tauIB = params->value(name, "tauIB");

   if (params->present(name, "VthRest"))  cp->VthRest  = params->value(name, "VthRest");
   if (params->present(name, "tauVth"))   cp->tauVth   = params->value(name, "tauVth");
   if (params->present(name, "deltaVth")) cp->deltaVth = params->value(name, "deltaVth");
   if (params->present(name, "deltaVthDecay")) cp->deltaVthDecay = params->value(name, "deltaVthDecay");

   if (params->present(name, "noiseAmpE"))   cp->noiseAmpE   = params->value(name, "noiseAmpE");
   if (params->present(name, "noiseAmpI"))   cp->noiseAmpI   = params->value(name, "noiseAmpI");
   if (params->present(name, "noiseAmpIB"))  cp->noiseAmpIB  = params->value(name, "noiseAmpIB");

   if (params->present(name, "noiseFreqE")) {
      cp->noiseFreqE  = params->value(name, "noiseFreqE");
      if (dt * cp->noiseFreqE > 1.0) cp->noiseFreqE = 1.0 / dt;
   }
   if (params->present(name, "noiseFreqI")) {
      cp->noiseFreqI  = params->value(name, "noiseFreqI");
      if (dt * cp->noiseFreqI > 1.0) cp->noiseFreqI = 1.0 / dt;
   }
   if (params->present(name, "noiseFreqIB")) {
      cp->noiseFreqIB = params->value(name, "noiseFreqIB");
      if (dt * cp->noiseFreqIB > 1.0) cp->noiseFreqIB = 1.0 / dt;
   }

   return 0;
}

int V1::updateState(float time, float dt)
{
   PVParams * params = parent->parameters();
   int spikingFlag = 1;

   pv_debug_info("[%d]: V1::updateState:", clayer->columnId);

   if (params->present(clayer->name, "spikingFlag")) {
      spikingFlag = params->value(clayer->name, "spikingFlag");
   }

   if (spikingFlag != 0) {
      return LIF2_update_exact_linear(clayer, dt);
   }

   // just copy accumulation buffer to membrane potential
   // and activity buffer (nonspiking)

   pvdata_t * V = clayer->V;
   pvdata_t * phiExc   = clayer->phi[PHI_EXC];
   pvdata_t * phiInh   = clayer->phi[PHI_INH];
   pvdata_t * activity = clayer->activity->data;

   for (int k = 0; k < clayer->numNeurons; k++) {
#ifdef EXTEND_BORDER_INDEX
      int kPhi = kIndexExtended(k, clayer->loc.nx, clayer->loc.ny, clayer->numFeatures,
                                   clayer->numBorder);
#else
      int kPhi = k;
#endif
      V[k] = phiExc[kPhi] - phiInh[kPhi];
      activity[k] = V[k];

      // reset accumulation buffers
      phiExc[kPhi] = 0.0;
      phiInh[kPhi] = 0.0;
   }

   return 0;
}

int V1::writeState(const char * path, float time)
{
   HyPerLayer::writeState(path, time);

#ifdef DEBUG_OUTPUT
   // print activity at center of image

   int sx = clayer->numFeatures;
   int sy = sx*clayer->loc.nx;
   pvdata_t * a = clayer->activity->data;

   int n = (int) (sy*(clayer->loc.ny/2 - 1) + sx*(clayer->loc.nx/2));
   for (int f = 0; f < clayer->numFeatures; f++) {
      printf("f = %d, a[%d] = %f\n", f, n, a[n]);
      n += 1;
   }
   printf("\n");

   n = (int) (sy*(clayer->loc.ny/2 - 1) + sx*(clayer->loc.nx/2));
   n -= 8;
   for (int f = 0; f < clayer->numFeatures; f++) {
      printf("f = %d, a[%d] = %f\n", f, n, a[n]);
      n += 1;
   }
#endif

   return 0;
}

int V1::findPostSynaptic(int dim, int maxSize, int col,
// input: which layer, which neuron
		HyPerLayer *lSource, float pos[],

		// output: how many of our neurons are connected.
		// an array with their indices.
		// an array with their feature vectors.
		int* nNeurons, int nConnectedNeurons[], float *vPos)
{
	return 0;
}

} // namespace PV
<commit_msg>Removed deltaVthDecay (an experiment that should never have been committed).<commit_after>/*
 * V1.cpp
 *
 *  Created on: Jul 30, 2008
 *      Author: rasmussn
 */

#include "../include/pv_common.h"
#include "../include/default_params.h"
#include "../connections/PVConnection.h"
#include "HyPerLayer.hpp"
#include "V1.hpp"

#include <assert.h>
#include <float.h>
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

namespace PV
{

V1Params V1DefaultParams =
{
    V_REST, V_EXC, V_INH, V_INHB,            // V (mV)
    TAU_VMEM, TAU_EXC, TAU_INH, TAU_INHB,
    VTH_REST,  TAU_VTH, DELTA_VTH,	     // tau (ms)
    250, NOISE_AMP*( 1.0/TAU_EXC ) * ( ( TAU_INH * (V_REST-V_INH) + TAU_INHB * (V_REST-V_INHB) ) / (V_EXC-V_REST) ),
    250, NOISE_AMP*1.0,
    250, NOISE_AMP*1.0                       // noise (G)
};

V1::V1(const char* name, HyPerCol * hc)
{
   initialize(name, hc, TypeV1Simple);
}

V1::V1(const char* name, HyPerCol * hc, PVLayerType type)
{
   initialize(name, hc, type);
}

void V1::initialize(const char* name, HyPerCol * hc, PVLayerType type)
{
   setParent(hc);
   init(name, type);

   setParams(parent->parameters(), &V1DefaultParams);
   pvlayer_setFuncs(clayer, (INIT_FN) &LIF2_init, (UPDATE_FN) &LIF2_update_exact_linear);

   hc->addLayer(this);
}

int V1::setParams(PVParams * params, V1Params * p)
{
   const char * name = getName();
   float dt = .001 * parent->getDeltaTime();  // seconds

   clayer->params = (float *) malloc(sizeof(*p));
   memcpy(clayer->params, p, sizeof(*p));

   clayer->numParams = sizeof(*p) / sizeof(float);
   assert(clayer->numParams == 17);

   V1Params * cp = (V1Params *) clayer->params;

   if (params->present(name, "Vrest")) cp->Vrest = params->value(name, "Vrest");
   if (params->present(name, "Vexc"))  cp->Vexc  = params->value(name, "Vexc");
   if (params->present(name, "Vinh"))  cp->Vinh  = params->value(name, "Vinh");
   if (params->present(name, "VinhB")) cp->VinhB = params->value(name, "VinhB");

   if (params->present(name, "tau"))   cp->tau   = params->value(name, "tau");
   if (params->present(name, "tauE"))  cp->tauE  = params->value(name, "tauE");
   if (params->present(name, "tauI"))  cp->tauI  = params->value(name, "tauI");
   if (params->present(name, "tauIB")) cp->tauIB = params->value(name, "tauIB");

   if (params->present(name, "VthRest"))  cp->VthRest  = params->value(name, "VthRest");
   if (params->present(name, "tauVth"))   cp->tauVth   = params->value(name, "tauVth");
   if (params->present(name, "deltaVth")) cp->deltaVth = params->value(name, "deltaVth");

   if (params->present(name, "noiseAmpE"))   cp->noiseAmpE   = params->value(name, "noiseAmpE");
   if (params->present(name, "noiseAmpI"))   cp->noiseAmpI   = params->value(name, "noiseAmpI");
   if (params->present(name, "noiseAmpIB"))  cp->noiseAmpIB  = params->value(name, "noiseAmpIB");

   if (params->present(name, "noiseFreqE")) {
      cp->noiseFreqE  = params->value(name, "noiseFreqE");
      if (dt * cp->noiseFreqE > 1.0) cp->noiseFreqE = 1.0 / dt;
   }
   if (params->present(name, "noiseFreqI")) {
      cp->noiseFreqI  = params->value(name, "noiseFreqI");
      if (dt * cp->noiseFreqI > 1.0) cp->noiseFreqI = 1.0 / dt;
   }
   if (params->present(name, "noiseFreqIB")) {
      cp->noiseFreqIB = params->value(name, "noiseFreqIB");
      if (dt * cp->noiseFreqIB > 1.0) cp->noiseFreqIB = 1.0 / dt;
   }

   return 0;
}

int V1::updateState(float time, float dt)
{
   PVParams * params = parent->parameters();
   int spikingFlag = 1;

   pv_debug_info("[%d]: V1::updateState:", clayer->columnId);

   if (params->present(clayer->name, "spikingFlag")) {
      spikingFlag = params->value(clayer->name, "spikingFlag");
   }

   if (spikingFlag != 0) {
      return LIF2_update_exact_linear(clayer, dt);
   }

   // just copy accumulation buffer to membrane potential
   // and activity buffer (nonspiking)

   pvdata_t * V = clayer->V;
   pvdata_t * phiExc   = clayer->phi[PHI_EXC];
   pvdata_t * phiInh   = clayer->phi[PHI_INH];
   pvdata_t * activity = clayer->activity->data;

   for (int k = 0; k < clayer->numNeurons; k++) {
#ifdef EXTEND_BORDER_INDEX
      int kPhi = kIndexExtended(k, clayer->loc.nx, clayer->loc.ny, clayer->numFeatures,
                                   clayer->numBorder);
#else
      int kPhi = k;
#endif
      V[k] = phiExc[kPhi] - phiInh[kPhi];
      activity[k] = V[k];

      // reset accumulation buffers
      phiExc[kPhi] = 0.0;
      phiInh[kPhi] = 0.0;
   }

   return 0;
}

int V1::writeState(const char * path, float time)
{
   HyPerLayer::writeState(path, time);

#ifdef DEBUG_OUTPUT
   // print activity at center of image

   int sx = clayer->numFeatures;
   int sy = sx*clayer->loc.nx;
   pvdata_t * a = clayer->activity->data;

   int n = (int) (sy*(clayer->loc.ny/2 - 1) + sx*(clayer->loc.nx/2));
   for (int f = 0; f < clayer->numFeatures; f++) {
      printf("f = %d, a[%d] = %f\n", f, n, a[n]);
      n += 1;
   }
   printf("\n");

   n = (int) (sy*(clayer->loc.ny/2 - 1) + sx*(clayer->loc.nx/2));
   n -= 8;
   for (int f = 0; f < clayer->numFeatures; f++) {
      printf("f = %d, a[%d] = %f\n", f, n, a[n]);
      n += 1;
   }
#endif

   return 0;
}

int V1::findPostSynaptic(int dim, int maxSize, int col,
// input: which layer, which neuron
		HyPerLayer *lSource, float pos[],

		// output: how many of our neurons are connected.
		// an array with their indices.
		// an array with their feature vectors.
		int* nNeurons, int nConnectedNeurons[], float *vPos)
{
	return 0;
}

} // namespace PV
<|endoftext|>


<commit_before>
/**
 * @ingroup tracking_algorithms
 * @file
 * Implementation of Correlation
 *
 * @author Manuel Huber <huberma@in.tum.de>
 */

#include "Correlation.h"

#ifdef HAVE_LAPACK

namespace Ubitrack { namespace Calibration {

double computeCorrelationDirect ( const std::vector< double >& left,
								  const std::vector< double >& right)
{
	double res = 0.0;
	size_t len = left.size() < right.size() ? left.size() : right.size();

	double var1 = 0.0;
	double var2 = 0.0;

	double m1 = 0.0;
	double m2 = 0.0;

	for (int i=0; i<len; i++) {
		m1 += left[i];
		m2 += right[i];
	}
	m1 /= (double)(len);
	m2 /= (double)(len);

	for (int i=0; i<len; i++) {
		res += (left[i]-m1)*(right[i]-m2);
		var1 += (left[i]-m1)*(left[i]-m1);
		var2 += (right[i]-m2)*(right[i]-m2);
	}

	double denom = sqrt(var1*var2);

	return res/denom;
}

double computeCorrelation ( const std::vector< double >& left,
							const std::vector< double >& right)
{
	if (left.size() == 0 && right.size() == 0) {
		return 1.0f;
	}

	return computeCorrelationDirect(left,right);
}

} } // namespace Ubitrack::Calibration

#endif // HAVE_LAPACK
<commit_msg>fixes to compile on linux<commit_after>
/**
 * @ingroup tracking_algorithms
 * @file
 * Implementation of Correlation
 *
 * @author Manuel Huber <huberma@in.tum.de>
 */

#include "Correlation.h"
#include <math.h>

#ifdef HAVE_LAPACK

namespace Ubitrack { namespace Calibration {

double computeCorrelationDirect ( const std::vector< double >& left,
								  const std::vector< double >& right)
{
	double res = 0.0;
	std::size_t len = left.size() < right.size() ? left.size() : right.size();

	double var1 = 0.0;
	double var2 = 0.0;

	double m1 = 0.0;
	double m2 = 0.0;

	for (int i=0; i<len; i++) {
		m1 += left[i];
		m2 += right[i];
	}
	m1 /= (double)(len);
	m2 /= (double)(len);

	for (int i=0; i<len; i++) {
		res += (left[i]-m1)*(right[i]-m2);
		var1 += (left[i]-m1)*(left[i]-m1);
		var2 += (right[i]-m2)*(right[i]-m2);
	}

	double denom = sqrt(var1*var2);

	return res/denom;
}

double computeCorrelation ( const std::vector< double >& left,
							const std::vector< double >& right)
{
	if (left.size() == 0 && right.size() == 0) {
		return 1.0f;
	}

	return computeCorrelationDirect(left,right);
}

} } // namespace Ubitrack::Calibration

#endif // HAVE_LAPACK
<|endoftext|>


<commit_before>#include <reactive/bridge.hpp>
#include <reactive/consume.hpp>
#include <boost/optional.hpp>
#include <boost/test/unit_test.hpp>
#include <lua.hpp>

namespace Si
{
	struct lua_deleter
	{
		void operator()(lua_State *L) const
		{
			lua_close(L);
		}
	};

	std::unique_ptr<lua_State, lua_deleter> open_lua()
	{
		auto L = std::unique_ptr<lua_State, lua_deleter>(luaL_newstate());
		if (!L)
		{
			throw std::bad_alloc();
		}
		return L;
	}

	typedef rx::observer<int> yield_destination;

	static int yield(lua_State *L)
	{
		yield_destination &dest = *static_cast<yield_destination *>(lua_touserdata(L, lua_upvalueindex(1)));
		int element = lua_tointeger(L, 1);
		dest.got_element(element);
		return lua_yield(L, 0);
	}

	BOOST_AUTO_TEST_CASE(lua)
	{
		auto L = open_lua();

		lua_State * const coro = lua_newthread(L.get());
		BOOST_REQUIRE_EQUAL(0, luaL_loadstring(coro, "return function (yield) yield(4) yield(5) end"));
		if (0 != lua_pcall(coro, 0, 1, 0))
		{
			throw std::runtime_error(lua_tostring(L.get(), -1));
		}

		rx::bridge<int> yielded;
		// fn &yielded
		lua_pushlightuserdata(coro, &static_cast<yield_destination &>(yielded));
		// fn yield[&yielded]
		lua_pushcclosure(coro, yield, 1);

		boost::optional<int> got;
		auto consumer = rx::consume<int>([&got](boost::optional<int> element)
		{
			BOOST_REQUIRE(element);
			got = element;
		});

		{
			yielded.async_get_one(consumer);
			int rc = lua_resume(coro, 1);
			if (LUA_YIELD != rc)
			{
				throw std::runtime_error(lua_tostring(coro, -1));
			}
			BOOST_CHECK_EQUAL(boost::make_optional(4), got);
		}

		{
			yielded.async_get_one(consumer);
			int rc = lua_resume(coro, 1);
			if (LUA_YIELD != rc)
			{
				throw std::runtime_error(lua_tostring(coro, -1));
			}
			BOOST_CHECK_EQUAL(boost::make_optional(5), got);
		}
	}
}
<commit_msg>observable Lua thread in progress<commit_after>#include <reactive/bridge.hpp>
#include <reactive/consume.hpp>
#include <boost/optional.hpp>
#include <boost/test/unit_test.hpp>
#include <lua.hpp>

namespace Si
{
	struct lua_deleter
	{
		void operator()(lua_State *L) const
		{
			lua_close(L);
		}
	};

	std::unique_ptr<lua_State, lua_deleter> open_lua()
	{
		auto L = std::unique_ptr<lua_State, lua_deleter>(luaL_newstate());
		if (!L)
		{
			throw std::bad_alloc();
		}
		return L;
	}

	typedef rx::observer<lua_Integer> yield_destination;

	static int yield(lua_State *L)
	{
		yield_destination &dest = *static_cast<yield_destination *>(lua_touserdata(L, lua_upvalueindex(1)));
		lua_Integer element = lua_tointeger(L, 1);
		dest.got_element(element);
		return lua_yield(L, 0);
	}

	BOOST_AUTO_TEST_CASE(lua)
	{
		auto L = open_lua();

		lua_State * const coro = lua_newthread(L.get());
		BOOST_REQUIRE_EQUAL(0, luaL_loadstring(coro, "return function (yield) yield(4) yield(5) end"));
		if (0 != lua_pcall(coro, 0, 1, 0))
		{
			throw std::runtime_error(lua_tostring(L.get(), -1));
		}

		rx::bridge<lua_Integer> yielded;
		lua_pushlightuserdata(coro, &static_cast<yield_destination &>(yielded));
		lua_pushcclosure(coro, yield, 1);

		boost::optional<lua_Integer> got;
		auto consumer = rx::consume<lua_Integer>([&got](boost::optional<lua_Integer> element)
		{
			BOOST_REQUIRE(element);
			got = element;
		});

		{
			yielded.async_get_one(consumer);
			int rc = lua_resume(coro, 1);
			if (LUA_YIELD != rc)
			{
				throw std::runtime_error(lua_tostring(coro, -1));
			}
			BOOST_CHECK_EQUAL(boost::make_optional<lua_Integer>(4), got);
		}

		{
			yielded.async_get_one(consumer);
			int rc = lua_resume(coro, 1);
			if (LUA_YIELD != rc)
			{
				throw std::runtime_error(lua_tostring(coro, -1));
			}
			BOOST_CHECK_EQUAL(boost::make_optional<lua_Integer>(5), got);
		}
	}
}

namespace rx
{
	template <class Element, class ElementFromLua>
	struct lua_thread : public observable<Element>
	{
		using element_type = Element;

		explicit lua_thread(lua_State &thread, ElementFromLua from_lua)
			: s(std::make_shared<state>(thread, std::move(from_lua)))
		{
		}

		virtual void async_get_one(observer<element_type> &receiver) SILICIUM_OVERRIDE
		{
			s->receiver = &receiver;
			if (s->was_resumed)
			{
				lua_resume(s->thread, 0);
			}
			else
			{
				void *bound_state = lua_newuserdata(s->thread, sizeof(weak_state));
				new (static_cast<weak_state *>(bound_state)) weak_state(s);
				//TODO __gc
				//TODO error handling
				lua_pushcclosure(s->thread, lua_thread::yield, 1);
				lua_resume(s->thread, 1);
			}
		}

		virtual void cancel() SILICIUM_OVERRIDE
		{
			s.reset();
		}

	private:

		struct state
		{
			//TODO: keep the Lua thread alive
			lua_State *thread = nullptr;
			ElementFromLua from_lua;
			bool was_resumed = false;
			observer<element_type> *receiver = nullptr;

			explicit state(lua_State &thread, ElementFromLua from_lua)
				: thread(&thread)
				, from_lua(std::move(from_lua))
			{
			}
		};
		typedef std::weak_ptr<state> weak_state;

		std::shared_ptr<state> s;

		static int yield(lua_State *thread)
		{
			weak_state * const bound_state = static_cast<weak_state *>(lua_touserdata(thread, lua_upvalueindex(1)));
			std::shared_ptr<state> locked_state = bound_state->lock();
			if (!locked_state)
			{
				return 0;
			}
			assert(locked_state->receiver);
			exchange(locked_state->receiver, nullptr)->got_element(locked_state->from_lua(*thread, -1));
			return 0;
		}
	};

	inline void swap_top(lua_State &lua)
	{
		lua_pushvalue(&lua, -2);
		lua_remove(&lua, -3);
	}

	template <class Element, class ElementFromLua>
	auto make_lua_thread(lua_State &parent, ElementFromLua &&from_lua)
	{
		lua_State * const coro = lua_newthread(&parent);
		lua_xmove(&parent, coro, 2);
		swap_top(*coro);
		return lua_thread<Element, typename std::decay<ElementFromLua>::type>(parent, std::forward<ElementFromLua>(from_lua));
	}
}

namespace Si
{
	BOOST_AUTO_TEST_CASE(lua_thread_observable)
	{
		auto L = open_lua();
		BOOST_REQUIRE_EQUAL(0, luaL_loadstring(L.get(), "return function (yield) yield(4) yield(5) end"));
		if (0 != lua_pcall(L.get(), 0, 1, 0))
		{
			throw std::runtime_error(lua_tostring(L.get(), -1));
		}

		auto thread = rx::make_lua_thread<lua_Integer>(*L, [](lua_State &lua, int idx) -> lua_Integer { return lua_tointeger(&lua, idx); });
	}
}
<|endoftext|>


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

#include "common.h"
#include "eventpipeeventinstance.h"
#include "eventpipejsonfile.h"
#include "fastserializer.h"
#include "sampleprofiler.h"

#ifdef FEATURE_PERFTRACING

EventPipeEventInstance::EventPipeEventInstance(
    EventPipeEvent &event,
    DWORD threadID,
    BYTE *pData,
    unsigned int length)
{
    CONTRACTL
    {
        THROWS;
        GC_TRIGGERS;
        MODE_ANY;
    }
    CONTRACTL_END;

#ifdef _DEBUG
    m_debugEventStart = 0xDEADBEEF;
    m_debugEventEnd = 0xCAFEBABE;
#endif // _DEBUG
    m_pEvent = &event;
    m_threadID = threadID;
    m_pData = pData;
    m_dataLength = length;
    QueryPerformanceCounter(&m_timeStamp);

    if(event.NeedStack())
    {
        EventPipe::WalkManagedStackForCurrentThread(m_stackContents);
    }

#ifdef _DEBUG
    EnsureConsistency();
#endif // _DEBUG
}

StackContents* EventPipeEventInstance::GetStack()
{
    LIMITED_METHOD_CONTRACT;

    return &m_stackContents;
}

EventPipeEvent* EventPipeEventInstance::GetEvent() const
{
    LIMITED_METHOD_CONTRACT;

    return m_pEvent;
}

LARGE_INTEGER EventPipeEventInstance::GetTimeStamp() const
{
    LIMITED_METHOD_CONTRACT;

    return m_timeStamp;
}

BYTE* EventPipeEventInstance::GetData() const
{
    LIMITED_METHOD_CONTRACT;

    return m_pData;
}

unsigned int EventPipeEventInstance::GetLength() const
{
    LIMITED_METHOD_CONTRACT;

    return m_dataLength;
}

void EventPipeEventInstance::FastSerialize(FastSerializer *pSerializer, StreamLabel metadataLabel)
{
    CONTRACTL
    {
        THROWS;
        GC_TRIGGERS;
        MODE_ANY;
    }
    CONTRACTL_END;

#ifdef _DEBUG
    // Useful for diagnosing serialization bugs.
    const unsigned int value = 0xDEADBEEF;
    pSerializer->WriteBuffer((BYTE*)&value, sizeof(value));
#endif

    // Calculate the size of the total payload so that it can be written to the file.
    unsigned int payloadLength =
        sizeof(metadataLabel) +
        sizeof(m_threadID) +        // Thread ID
        sizeof(m_timeStamp) +       // TimeStamp
        m_dataLength +              // Event payload data length
        m_stackContents.GetSize();  // Stack payload size

    // Write the size of the event to the file.
    pSerializer->WriteBuffer((BYTE*)&payloadLength, sizeof(payloadLength));

    // Write the metadata label.
    pSerializer->WriteBuffer((BYTE*)&metadataLabel, sizeof(metadataLabel));

    // Write the thread ID.
    pSerializer->WriteBuffer((BYTE*)&m_threadID, sizeof(m_threadID));

    // Write the timestamp.
    pSerializer->WriteBuffer((BYTE*)&m_timeStamp, sizeof(m_timeStamp));

    // Write the event data payload.
    if(m_dataLength > 0)
    {
        pSerializer->WriteBuffer(m_pData, m_dataLength);
    }

    // Write the stack if present.
    if(m_stackContents.GetSize() > 0)
    {
        pSerializer->WriteBuffer(m_stackContents.GetPointer(), m_stackContents.GetSize());
    }
}

#ifdef _DEBUG
void EventPipeEventInstance::SerializeToJsonFile(EventPipeJsonFile *pFile)
{
    CONTRACTL
    {
        NOTHROW;
        GC_NOTRIGGER;
        MODE_ANY;
    }
    CONTRACTL_END;

    if(pFile == NULL)
    {
        return;
    }

    EX_TRY
    {
        const unsigned int guidSize = 39;
        WCHAR wszProviderID[guidSize];
        if(!StringFromGUID2(m_pEvent->GetProvider()->GetProviderID(), wszProviderID, guidSize))
        {
            wszProviderID[0] = '\0';
        }

        // Strip off the {}.
        StackScratchBuffer scratch;
        SString guidStr(&wszProviderID[1], guidSize-3);

        SString message;
        message.Printf("Provider=%s/EventID=%d/Version=%d", guidStr.GetANSI(scratch), m_pEvent->GetEventID(), m_pEvent->GetEventVersion());
        pFile->WriteEvent(m_timeStamp, m_threadID, message, m_stackContents);
    }
    EX_CATCH{} EX_END_CATCH(SwallowAllExceptions);
}
#endif

void EventPipeEventInstance::SetTimeStamp(LARGE_INTEGER timeStamp)
{
    LIMITED_METHOD_CONTRACT;

    m_timeStamp = timeStamp;
}

#ifdef _DEBUG
bool EventPipeEventInstance::EnsureConsistency()
{
    CONTRACTL
    {
        NOTHROW;
        GC_NOTRIGGER;
        MODE_ANY;
    }
    CONTRACTL_END;

    // Validate event start.
    _ASSERTE(m_debugEventStart == 0xDEADBEEF);

    // Validate event end.
    _ASSERTE(m_debugEventEnd == 0xCAFEBABE);

    return true;
}
#endif // _DEBUG

SampleProfilerEventInstance::SampleProfilerEventInstance(Thread *pThread)
    :EventPipeEventInstance(*SampleProfiler::s_pThreadTimeEvent, pThread->GetOSThreadId(), NULL, 0)
{
    LIMITED_METHOD_CONTRACT;
}

#endif // FEATURE_PERFTRACING
<commit_msg>Put the serialization marker under its own IFDEF. (#11568)<commit_after>// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.

#include "common.h"
#include "eventpipeeventinstance.h"
#include "eventpipejsonfile.h"
#include "fastserializer.h"
#include "sampleprofiler.h"

#ifdef FEATURE_PERFTRACING

EventPipeEventInstance::EventPipeEventInstance(
    EventPipeEvent &event,
    DWORD threadID,
    BYTE *pData,
    unsigned int length)
{
    CONTRACTL
    {
        THROWS;
        GC_TRIGGERS;
        MODE_ANY;
    }
    CONTRACTL_END;

#ifdef _DEBUG
    m_debugEventStart = 0xDEADBEEF;
    m_debugEventEnd = 0xCAFEBABE;
#endif // _DEBUG
    m_pEvent = &event;
    m_threadID = threadID;
    m_pData = pData;
    m_dataLength = length;
    QueryPerformanceCounter(&m_timeStamp);

    if(event.NeedStack())
    {
        EventPipe::WalkManagedStackForCurrentThread(m_stackContents);
    }

#ifdef _DEBUG
    EnsureConsistency();
#endif // _DEBUG
}

StackContents* EventPipeEventInstance::GetStack()
{
    LIMITED_METHOD_CONTRACT;

    return &m_stackContents;
}

EventPipeEvent* EventPipeEventInstance::GetEvent() const
{
    LIMITED_METHOD_CONTRACT;

    return m_pEvent;
}

LARGE_INTEGER EventPipeEventInstance::GetTimeStamp() const
{
    LIMITED_METHOD_CONTRACT;

    return m_timeStamp;
}

BYTE* EventPipeEventInstance::GetData() const
{
    LIMITED_METHOD_CONTRACT;

    return m_pData;
}

unsigned int EventPipeEventInstance::GetLength() const
{
    LIMITED_METHOD_CONTRACT;

    return m_dataLength;
}

void EventPipeEventInstance::FastSerialize(FastSerializer *pSerializer, StreamLabel metadataLabel)
{
    CONTRACTL
    {
        THROWS;
        GC_TRIGGERS;
        MODE_ANY;
    }
    CONTRACTL_END;

#ifdef EVENTPIPE_EVENT_MARKER
    // Useful for diagnosing serialization bugs.
    const unsigned int value = 0xDEADBEEF;
    pSerializer->WriteBuffer((BYTE*)&value, sizeof(value));
#endif

    // Calculate the size of the total payload so that it can be written to the file.
    unsigned int payloadLength =
        sizeof(metadataLabel) +
        sizeof(m_threadID) +        // Thread ID
        sizeof(m_timeStamp) +       // TimeStamp
        m_dataLength +              // Event payload data length
        m_stackContents.GetSize();  // Stack payload size

    // Write the size of the event to the file.
    pSerializer->WriteBuffer((BYTE*)&payloadLength, sizeof(payloadLength));

    // Write the metadata label.
    pSerializer->WriteBuffer((BYTE*)&metadataLabel, sizeof(metadataLabel));

    // Write the thread ID.
    pSerializer->WriteBuffer((BYTE*)&m_threadID, sizeof(m_threadID));

    // Write the timestamp.
    pSerializer->WriteBuffer((BYTE*)&m_timeStamp, sizeof(m_timeStamp));

    // Write the event data payload.
    if(m_dataLength > 0)
    {
        pSerializer->WriteBuffer(m_pData, m_dataLength);
    }

    // Write the stack if present.
    if(m_stackContents.GetSize() > 0)
    {
        pSerializer->WriteBuffer(m_stackContents.GetPointer(), m_stackContents.GetSize());
    }
}

#ifdef _DEBUG
void EventPipeEventInstance::SerializeToJsonFile(EventPipeJsonFile *pFile)
{
    CONTRACTL
    {
        NOTHROW;
        GC_NOTRIGGER;
        MODE_ANY;
    }
    CONTRACTL_END;

    if(pFile == NULL)
    {
        return;
    }

    EX_TRY
    {
        const unsigned int guidSize = 39;
        WCHAR wszProviderID[guidSize];
        if(!StringFromGUID2(m_pEvent->GetProvider()->GetProviderID(), wszProviderID, guidSize))
        {
            wszProviderID[0] = '\0';
        }

        // Strip off the {}.
        StackScratchBuffer scratch;
        SString guidStr(&wszProviderID[1], guidSize-3);

        SString message;
        message.Printf("Provider=%s/EventID=%d/Version=%d", guidStr.GetANSI(scratch), m_pEvent->GetEventID(), m_pEvent->GetEventVersion());
        pFile->WriteEvent(m_timeStamp, m_threadID, message, m_stackContents);
    }
    EX_CATCH{} EX_END_CATCH(SwallowAllExceptions);
}
#endif

void EventPipeEventInstance::SetTimeStamp(LARGE_INTEGER timeStamp)
{
    LIMITED_METHOD_CONTRACT;

    m_timeStamp = timeStamp;
}

#ifdef _DEBUG
bool EventPipeEventInstance::EnsureConsistency()
{
    CONTRACTL
    {
        NOTHROW;
        GC_NOTRIGGER;
        MODE_ANY;
    }
    CONTRACTL_END;

    // Validate event start.
    _ASSERTE(m_debugEventStart == 0xDEADBEEF);

    // Validate event end.
    _ASSERTE(m_debugEventEnd == 0xCAFEBABE);

    return true;
}
#endif // _DEBUG

SampleProfilerEventInstance::SampleProfilerEventInstance(Thread *pThread)
    :EventPipeEventInstance(*SampleProfiler::s_pThreadTimeEvent, pThread->GetOSThreadId(), NULL, 0)
{
    LIMITED_METHOD_CONTRACT;
}

#endif // FEATURE_PERFTRACING
<|endoftext|>


<commit_before>#include <type_traits>
#include <cassert>
#include <map>
#include <string>
#include <duktape.h>
#include <gtest/gtest.h>
#include <entt/core/type_info.hpp>
#include <entt/entity/registry.hpp>

template<typename Type>
struct tag { using type = Type; };

struct position {
    double x;
    double y;
};

struct renderable {};

struct duktape_runtime {
    std::map<duk_uint_t, std::string> components;
};

template<typename Comp>
duk_ret_t set(duk_context *ctx, entt::registry &registry) {
    const entt::entity entity{duk_require_uint(ctx, 0)};

    if constexpr(std::is_same_v<Comp, position>) {
        const auto x = duk_require_number(ctx, 2);
        const auto y = duk_require_number(ctx, 3);
        registry.assign_or_replace<position>(entity, x, y);
    } else if constexpr(std::is_same_v<Comp, duktape_runtime>) {
        const auto type = duk_require_uint(ctx, 1);

        duk_dup(ctx, 2);

        if(!registry.has<duktape_runtime>(entity)) {
            registry.assign<duktape_runtime>(entity).components[type] = duk_json_encode(ctx, -1);
        } else {
            registry.get<duktape_runtime>(entity).components[type] = duk_json_encode(ctx, -1);
        }

        duk_pop(ctx);
    } else {
        registry.assign_or_replace<Comp>(entity);
    }

    return 0;
}

template<typename Comp>
duk_ret_t unset(duk_context *ctx, entt::registry &registry) {
    const entt::entity entity{duk_require_uint(ctx, 0)};

    if constexpr(std::is_same_v<Comp, duktape_runtime>) {
        const auto type = duk_require_uint(ctx, 1);

        auto &components = registry.get<duktape_runtime>(entity).components;
        assert(components.find(type) != components.cend());
        components.erase(type);

        if(components.empty()) {
            registry.remove<duktape_runtime>(entity);
        }
    } else {
        registry.remove<Comp>(entity);
    }

    return 0;
}

template<typename Comp>
duk_ret_t has(duk_context *ctx, entt::registry &registry) {
    const entt::entity entity{duk_require_uint(ctx, 0)};

    if constexpr(std::is_same_v<Comp, duktape_runtime>) {
        duk_push_boolean(ctx, registry.has<duktape_runtime>(entity));

        if(registry.has<duktape_runtime>(entity)) {
            const auto type = duk_require_uint(ctx, 1);
            const auto &components = registry.get<duktape_runtime>(entity).components;
            duk_push_boolean(ctx, components.find(type) != components.cend());
        } else {
            duk_push_false(ctx);
        }
    } else {
        duk_push_boolean(ctx, registry.has<Comp>(entity));
    }

    return 1;
}

template<typename Comp>
duk_ret_t get(duk_context *ctx, entt::registry &registry) {
    [[maybe_unused]] const entt::entity entity{duk_require_uint(ctx, 0)};

    if constexpr(std::is_same_v<Comp, position>) {
        const auto &pos = registry.get<position>(entity);

        const auto idx = duk_push_object(ctx);

        duk_push_string(ctx, "x");
        duk_push_number(ctx, pos.x);
        duk_def_prop(ctx, idx, DUK_DEFPROP_HAVE_VALUE);

        duk_push_string(ctx, "y");
        duk_push_number(ctx, pos.y);
        duk_def_prop(ctx, idx, DUK_DEFPROP_HAVE_VALUE);
    } if constexpr(std::is_same_v<Comp, duktape_runtime>) {
        const auto type = duk_require_uint(ctx, 1);

        auto &runtime = registry.get<duktape_runtime>(entity);
        assert(runtime.components.find(type) != runtime.components.cend());

        duk_push_string(ctx, runtime.components[type].c_str());
        duk_json_decode(ctx, -1);
    } else {
        assert(registry.has<Comp>(entity));
        duk_push_object(ctx);
    }

    return 1;
}

class duktape_registry {
    struct func_map {
        using func_type = duk_ret_t(*)(duk_context *, entt::registry &);

        func_type set;
        func_type unset;
        func_type has;
        func_type get;
    };

    template<typename... Comp>
    void reg() {
        ((func[entt::type_info<Comp>::id()] = {
                &::set<Comp>,
                &::unset<Comp>,
                &::has<Comp>,
                &::get<Comp>
        }), ...);
    }

    static duktape_registry & instance(duk_context *ctx) {
        duk_push_this(ctx);

        duk_push_string(ctx, DUK_HIDDEN_SYMBOL("dreg"));
        duk_get_prop(ctx, -2);
        auto &dreg = *static_cast<duktape_registry *>(duk_require_pointer(ctx, -1));
        duk_pop_2(ctx);

        return dreg;
    }

    template<func_map::func_type func_map::*Op>
    static duk_ret_t invoke(duk_context *ctx) {
        auto &dreg = instance(ctx);
        auto &func = dreg.func;
        auto &registry = dreg.registry;
        auto type = duk_require_uint(ctx, 1);

        const auto it = func.find(type);

        return (it == func.cend())
                ? (func[entt::type_info<duktape_runtime>::id()].*Op)(ctx, registry)
                : (it->second.*Op)(ctx, registry);
    }

public:
    duktape_registry(entt::registry &ref)
        : registry{ref}
    {
        reg<position, renderable, duktape_runtime>();
    }

    static duk_ret_t identifier(duk_context *ctx) {
        static ENTT_ID_TYPE next{};
        duk_push_uint(ctx, next++);
        return 1;
    }

    static duk_ret_t create(duk_context *ctx) {
        auto &dreg = instance(ctx);
        const auto entity = dreg.registry.create();
        duk_push_uint(ctx, static_cast<std::underlying_type_t<entt::entity>>(entity));
        return 1;
    }

    static duk_ret_t set(duk_context *ctx) {
        return invoke<&func_map::set>(ctx);
    }

    static duk_ret_t unset(duk_context *ctx) {
        return invoke<&func_map::unset>(ctx);
    }

    static duk_ret_t has(duk_context *ctx) {
        return invoke<&func_map::has>(ctx);
    }

    static duk_ret_t get(duk_context *ctx) {
        return invoke<&func_map::get>(ctx);
    }

    static duk_ret_t entities(duk_context *ctx) {
        const duk_idx_t nargs = duk_get_top(ctx);
        auto &dreg = instance(ctx);

        duk_push_array(ctx);

        std::vector<ENTT_ID_TYPE> components;
        std::vector<ENTT_ID_TYPE> runtime;

        for(duk_idx_t arg = 0; arg < nargs; arg++) {
            auto type = duk_require_uint(ctx, arg);

            if(dreg.func.find(type) == dreg.func.cend()) {
                if(runtime.empty()) {
                    components.push_back(entt::type_info<duktape_runtime>::id());
                }

                runtime.push_back(type);
            } else {
                components.push_back(type);
            }
        }

        auto view = dreg.registry.runtime_view(components.cbegin(), components.cend());
        duk_uarridx_t pos = 0;

        for(const auto entity: view) {
            if(runtime.empty()) {
                duk_push_uint(ctx, static_cast<std::underlying_type_t<entt::entity>>(entity));
                duk_put_prop_index(ctx, -2, pos++);
            } else {
                const auto &others = dreg.registry.get<duktape_runtime>(entity).components;
                const auto match = std::all_of(runtime.cbegin(), runtime.cend(), [&others](const auto type) {
                    return others.find(type) != others.cend();
                });

                if(match) {
                    duk_push_uint(ctx, static_cast<std::underlying_type_t<entt::entity>>(entity));
                    duk_put_prop_index(ctx, -2, pos++);
                }
            }
        }

        return 1;
    }

private:
    std::map<duk_uint_t, func_map> func;
    entt::registry &registry;
};

const duk_function_list_entry js_duktape_registry_methods[] = {
    { "identifier", &duktape_registry::identifier, 0 },
    { "create", &duktape_registry::create, 0 },
    { "set", &duktape_registry::set, DUK_VARARGS },
    { "unset", &duktape_registry::unset, 2 },
    { "has", &duktape_registry::has, 2 },
    { "get", &duktape_registry::get, 2 },
    { "entities", &duktape_registry::entities, DUK_VARARGS },
    { nullptr, nullptr, 0 }
};

void export_types(duk_context *context) {
    auto export_type = [idx = duk_push_object(context)](auto *ctx, auto type, const auto *name) {
        duk_push_string(ctx, name);
        duk_push_uint(ctx, entt::type_info<typename decltype(type)::type>::id());
        duk_def_prop(ctx, idx, DUK_DEFPROP_HAVE_VALUE | DUK_DEFPROP_CLEAR_WRITABLE);
    };

    export_type(context, tag<position>{}, "position");
    export_type(context, tag<renderable>{}, "renderable");

    duk_put_global_string(context, "Types");
}

void export_duktape_registry(duk_context *ctx, duktape_registry &dreg) {
    auto idx = duk_push_object(ctx);

    duk_push_string(ctx, DUK_HIDDEN_SYMBOL("dreg"));
    duk_push_pointer(ctx, &dreg);
    duk_put_prop(ctx, idx);

    duk_put_function_list(ctx, idx, js_duktape_registry_methods);
    duk_put_global_string(ctx, "Registry");
}

TEST(Mod, Duktape) {
    entt::registry registry;
    duktape_registry dreg{registry};
    duk_context *ctx = duk_create_heap_default();

    if(!ctx) {
        FAIL();
    }

    export_types(ctx);
    export_duktape_registry(ctx, dreg);

    const char *s0 = ""
            "Types[\"PLAYING_CHARACTER\"] = Registry.identifier();"
            "Types[\"VELOCITY\"] = Registry.identifier();"
            "";

    if(duk_peval_string(ctx, s0)) {
        FAIL();
    }

    const auto e0 = registry.create();
    registry.assign<position>(e0, 0., 0.);
    registry.assign<renderable>(e0);

    const auto e1 = registry.create();
    registry.assign<position>(e1, 0., 0.);

    const char *s1 = ""
            "Registry.entities(Types.position, Types.renderable).forEach(function(entity) {"
                "Registry.set(entity, Types.position, 100., 100.);"
            "});"
            "var entity = Registry.create();"
            "Registry.set(entity, Types.position, 100., 100.);"
            "Registry.set(entity, Types.renderable);"
            "";

    if(duk_peval_string(ctx, s1)) {
        FAIL();
    }

    ASSERT_EQ(registry.view<duktape_runtime>().size(), 0u);
    ASSERT_EQ(registry.view<position>().size(), 3u);
    ASSERT_EQ(registry.view<renderable>().size(), 2u);

    registry.view<position>().each([&registry](auto entity, const auto &position) {
        ASSERT_FALSE(registry.has<duktape_runtime>(entity));

        if(registry.has<renderable>(entity)) {
            ASSERT_EQ(position.x, 100.);
            ASSERT_EQ(position.y, 100.);
        } else {
            ASSERT_EQ(position.x, 0.);
            ASSERT_EQ(position.y, 0.);
        }
    });

    const char *s2 = ""
            "Registry.entities(Types.position).forEach(function(entity) {"
                "if(!Registry.has(entity, Types.renderable)) {"
                    "Registry.set(entity, Types.VELOCITY, { \"dx\": -100., \"dy\": -100. });"
                    "Registry.set(entity, Types.PLAYING_CHARACTER, {});"
                "}"
            "});"
            "";

    if(duk_peval_string(ctx, s2)) {
        FAIL();
    }

    ASSERT_EQ(registry.view<duktape_runtime>().size(), 1u);
    ASSERT_EQ(registry.view<position>().size(), 3u);
    ASSERT_EQ(registry.view<renderable>().size(), 2u);

    registry.view<duktape_runtime>().each([](const duktape_runtime &runtime) {
        ASSERT_EQ(runtime.components.size(), 2u);
    });

    const char *s3 = ""
            "Registry.entities(Types.position, Types.renderable, Types.VELOCITY, Types.PLAYING_CHARACTER).forEach(function(entity) {"
                "var velocity = Registry.get(entity, Types.VELOCITY);"
                "Registry.set(entity, Types.position, velocity.dx, velocity.dy)"
            "});"
            "";

    if(duk_peval_string(ctx, s3)) {
        FAIL();
    }

    ASSERT_EQ(registry.view<duktape_runtime>().size(), 1u);
    ASSERT_EQ(registry.view<position>().size(), 3u);
    ASSERT_EQ(registry.view<renderable>().size(), 2u);

    registry.view<position, renderable, duktape_runtime>().each([](const position &position, auto &&...) {
        ASSERT_EQ(position.x, -100.);
        ASSERT_EQ(position.y, -100.);
    });

    const char *s4 = ""
            "Registry.entities(Types.VELOCITY, Types.PLAYING_CHARACTER).forEach(function(entity) {"
                "Registry.unset(entity, Types.VELOCITY);"
                "Registry.unset(entity, Types.PLAYING_CHARACTER);"
            "});"
            "Registry.entities(Types.position).forEach(function(entity) {"
                "Registry.unset(entity, Types.position);"
            "});"
            "";

    if(duk_peval_string(ctx, s4)) {
        FAIL();
    }

    ASSERT_EQ(registry.view<duktape_runtime>().size(), 0u);
    ASSERT_EQ(registry.view<position>().size(), 0u);
    ASSERT_EQ(registry.view<renderable>().size(), 2u);

    duk_destroy_heap(ctx);
}
<commit_msg>test: minor changes<commit_after>#include <type_traits>
#include <cassert>
#include <map>
#include <string>
#include <duktape.h>
#include <gtest/gtest.h>
#include <entt/core/type_info.hpp>
#include <entt/entity/registry.hpp>

template<typename Type>
struct tag { using type = Type; };

struct position {
    double x;
    double y;
};

struct renderable {};

struct duktape_runtime {
    std::map<duk_uint_t, std::string> components;
};

template<typename Comp>
duk_ret_t set(duk_context *ctx, entt::registry &registry) {
    const entt::entity entity{duk_require_uint(ctx, 0)};

    if constexpr(std::is_same_v<Comp, position>) {
        const auto x = duk_require_number(ctx, 2);
        const auto y = duk_require_number(ctx, 3);
        registry.assign_or_replace<position>(entity, x, y);
    } else if constexpr(std::is_same_v<Comp, duktape_runtime>) {
        const auto type = duk_require_uint(ctx, 1);

        duk_dup(ctx, 2);

        if(!registry.has<duktape_runtime>(entity)) {
            registry.assign<duktape_runtime>(entity).components[type] = duk_json_encode(ctx, -1);
        } else {
            registry.get<duktape_runtime>(entity).components[type] = duk_json_encode(ctx, -1);
        }

        duk_pop(ctx);
    } else {
        registry.assign_or_replace<Comp>(entity);
    }

    return 0;
}

template<typename Comp>
duk_ret_t unset(duk_context *ctx, entt::registry &registry) {
    const entt::entity entity{duk_require_uint(ctx, 0)};

    if constexpr(std::is_same_v<Comp, duktape_runtime>) {
        const auto type = duk_require_uint(ctx, 1);

        auto &components = registry.get<duktape_runtime>(entity).components;
        assert(components.find(type) != components.cend());
        components.erase(type);

        if(components.empty()) {
            registry.remove<duktape_runtime>(entity);
        }
    } else {
        registry.remove<Comp>(entity);
    }

    return 0;
}

template<typename Comp>
duk_ret_t has(duk_context *ctx, entt::registry &registry) {
    const entt::entity entity{duk_require_uint(ctx, 0)};

    if constexpr(std::is_same_v<Comp, duktape_runtime>) {
        duk_push_boolean(ctx, registry.has<duktape_runtime>(entity));

        if(registry.has<duktape_runtime>(entity)) {
            const auto type = duk_require_uint(ctx, 1);
            const auto &components = registry.get<duktape_runtime>(entity).components;
            duk_push_boolean(ctx, components.find(type) != components.cend());
        } else {
            duk_push_false(ctx);
        }
    } else {
        duk_push_boolean(ctx, registry.has<Comp>(entity));
    }

    return 1;
}

template<typename Comp>
duk_ret_t get(duk_context *ctx, entt::registry &registry) {
    [[maybe_unused]] const entt::entity entity{duk_require_uint(ctx, 0)};

    if constexpr(std::is_same_v<Comp, position>) {
        const auto &pos = registry.get<position>(entity);

        const auto idx = duk_push_object(ctx);

        duk_push_string(ctx, "x");
        duk_push_number(ctx, pos.x);
        duk_def_prop(ctx, idx, DUK_DEFPROP_HAVE_VALUE);

        duk_push_string(ctx, "y");
        duk_push_number(ctx, pos.y);
        duk_def_prop(ctx, idx, DUK_DEFPROP_HAVE_VALUE);
    } if constexpr(std::is_same_v<Comp, duktape_runtime>) {
        const auto type = duk_require_uint(ctx, 1);

        auto &runtime = registry.get<duktape_runtime>(entity);
        assert(runtime.components.find(type) != runtime.components.cend());

        duk_push_string(ctx, runtime.components[type].c_str());
        duk_json_decode(ctx, -1);
    } else {
        assert(registry.has<Comp>(entity));
        duk_push_object(ctx);
    }

    return 1;
}

class duktape_registry {
    struct func_map {
        using func_type = duk_ret_t(*)(duk_context *, entt::registry &);

        func_type set;
        func_type unset;
        func_type has;
        func_type get;
    };

    template<typename... Comp>
    void reg() {
        ((func[entt::type_info<Comp>::id()] = {
                &::set<Comp>,
                &::unset<Comp>,
                &::has<Comp>,
                &::get<Comp>
        }), ...);
    }

    static duktape_registry & instance(duk_context *ctx) {
        duk_push_this(ctx);

        duk_push_string(ctx, DUK_HIDDEN_SYMBOL("dreg"));
        duk_get_prop(ctx, -2);
        auto &dreg = *static_cast<duktape_registry *>(duk_require_pointer(ctx, -1));
        duk_pop_2(ctx);

        return dreg;
    }

    template<func_map::func_type func_map::*Op>
    static duk_ret_t invoke(duk_context *ctx) {
        auto &dreg = instance(ctx);
        auto &func = dreg.func;
        auto &registry = dreg.registry;
        auto type = duk_require_uint(ctx, 1);

        const auto it = func.find(type);

        return (it == func.cend())
                ? (func[entt::type_info<duktape_runtime>::id()].*Op)(ctx, registry)
                : (it->second.*Op)(ctx, registry);
    }

public:
    duktape_registry(entt::registry &ref)
        : registry{ref}
    {
        reg<position, renderable, duktape_runtime>();
    }

    static duk_ret_t identifier(duk_context *ctx) {
        static ENTT_ID_TYPE next{1000u};
        duk_push_uint(ctx, next++);
        return 1;
    }

    static duk_ret_t create(duk_context *ctx) {
        auto &dreg = instance(ctx);
        const auto entity = dreg.registry.create();
        duk_push_uint(ctx, static_cast<std::underlying_type_t<entt::entity>>(entity));
        return 1;
    }

    static duk_ret_t set(duk_context *ctx) {
        return invoke<&func_map::set>(ctx);
    }

    static duk_ret_t unset(duk_context *ctx) {
        return invoke<&func_map::unset>(ctx);
    }

    static duk_ret_t has(duk_context *ctx) {
        return invoke<&func_map::has>(ctx);
    }

    static duk_ret_t get(duk_context *ctx) {
        return invoke<&func_map::get>(ctx);
    }

    static duk_ret_t entities(duk_context *ctx) {
        const duk_idx_t nargs = duk_get_top(ctx);
        auto &dreg = instance(ctx);

        duk_push_array(ctx);

        std::vector<ENTT_ID_TYPE> components;
        std::vector<ENTT_ID_TYPE> runtime;

        for(duk_idx_t arg = 0; arg < nargs; arg++) {
            auto type = duk_require_uint(ctx, arg);

            if(dreg.func.find(type) == dreg.func.cend()) {
                if(runtime.empty()) {
                    components.push_back(entt::type_info<duktape_runtime>::id());
                }

                runtime.push_back(type);
            } else {
                components.push_back(type);
            }
        }

        auto view = dreg.registry.runtime_view(components.cbegin(), components.cend());
        duk_uarridx_t pos = 0;

        for(const auto entity: view) {
            if(runtime.empty()) {
                duk_push_uint(ctx, static_cast<std::underlying_type_t<entt::entity>>(entity));
                duk_put_prop_index(ctx, -2, pos++);
            } else {
                const auto &others = dreg.registry.get<duktape_runtime>(entity).components;
                const auto match = std::all_of(runtime.cbegin(), runtime.cend(), [&others](const auto type) {
                    return others.find(type) != others.cend();
                });

                if(match) {
                    duk_push_uint(ctx, static_cast<std::underlying_type_t<entt::entity>>(entity));
                    duk_put_prop_index(ctx, -2, pos++);
                }
            }
        }

        return 1;
    }

private:
    std::map<duk_uint_t, func_map> func;
    entt::registry &registry;
};

const duk_function_list_entry js_duktape_registry_methods[] = {
    { "identifier", &duktape_registry::identifier, 0 },
    { "create", &duktape_registry::create, 0 },
    { "set", &duktape_registry::set, DUK_VARARGS },
    { "unset", &duktape_registry::unset, 2 },
    { "has", &duktape_registry::has, 2 },
    { "get", &duktape_registry::get, 2 },
    { "entities", &duktape_registry::entities, DUK_VARARGS },
    { nullptr, nullptr, 0 }
};

void export_types(duk_context *context) {
    auto export_type = [idx = duk_push_object(context)](auto *ctx, auto type, const auto *name) {
        duk_push_string(ctx, name);
        duk_push_uint(ctx, entt::type_info<typename decltype(type)::type>::id());
        duk_def_prop(ctx, idx, DUK_DEFPROP_HAVE_VALUE | DUK_DEFPROP_CLEAR_WRITABLE);
    };

    export_type(context, tag<position>{}, "position");
    export_type(context, tag<renderable>{}, "renderable");

    duk_put_global_string(context, "Types");
}

void export_duktape_registry(duk_context *ctx, duktape_registry &dreg) {
    auto idx = duk_push_object(ctx);

    duk_push_string(ctx, DUK_HIDDEN_SYMBOL("dreg"));
    duk_push_pointer(ctx, &dreg);
    duk_put_prop(ctx, idx);

    duk_put_function_list(ctx, idx, js_duktape_registry_methods);
    duk_put_global_string(ctx, "Registry");
}

TEST(Mod, Duktape) {
    entt::registry registry;
    duktape_registry dreg{registry};
    duk_context *ctx = duk_create_heap_default();

    if(!ctx) {
        FAIL();
    }

    export_types(ctx);
    export_duktape_registry(ctx, dreg);

    const char *s0 = ""
            "Types[\"PLAYING_CHARACTER\"] = Registry.identifier();"
            "Types[\"VELOCITY\"] = Registry.identifier();"
            "";

    if(duk_peval_string(ctx, s0)) {
        FAIL();
    }

    const auto e0 = registry.create();
    registry.assign<position>(e0, 0., 0.);
    registry.assign<renderable>(e0);

    const auto e1 = registry.create();
    registry.assign<position>(e1, 0., 0.);

    const char *s1 = ""
            "Registry.entities(Types.position, Types.renderable).forEach(function(entity) {"
                "Registry.set(entity, Types.position, 100., 100.);"
            "});"
            "var entity = Registry.create();"
            "Registry.set(entity, Types.position, 100., 100.);"
            "Registry.set(entity, Types.renderable);"
            "";

    if(duk_peval_string(ctx, s1)) {
        FAIL();
    }

    ASSERT_EQ(registry.view<duktape_runtime>().size(), 0u);
    ASSERT_EQ(registry.view<position>().size(), 3u);
    ASSERT_EQ(registry.view<renderable>().size(), 2u);

    registry.view<position>().each([&registry](auto entity, const auto &position) {
        ASSERT_FALSE(registry.has<duktape_runtime>(entity));

        if(registry.has<renderable>(entity)) {
            ASSERT_EQ(position.x, 100.);
            ASSERT_EQ(position.y, 100.);
        } else {
            ASSERT_EQ(position.x, 0.);
            ASSERT_EQ(position.y, 0.);
        }
    });

    const char *s2 = ""
            "Registry.entities(Types.position).forEach(function(entity) {"
                "if(!Registry.has(entity, Types.renderable)) {"
                    "Registry.set(entity, Types.VELOCITY, { \"dx\": -100., \"dy\": -100. });"
                    "Registry.set(entity, Types.PLAYING_CHARACTER, {});"
                "}"
            "});"
            "";

    if(duk_peval_string(ctx, s2)) {
        FAIL();
    }

    ASSERT_EQ(registry.view<duktape_runtime>().size(), 1u);
    ASSERT_EQ(registry.view<position>().size(), 3u);
    ASSERT_EQ(registry.view<renderable>().size(), 2u);

    registry.view<duktape_runtime>().each([](const duktape_runtime &runtime) {
        ASSERT_EQ(runtime.components.size(), 2u);
    });

    const char *s3 = ""
            "Registry.entities(Types.position, Types.renderable, Types.VELOCITY, Types.PLAYING_CHARACTER).forEach(function(entity) {"
                "var velocity = Registry.get(entity, Types.VELOCITY);"
                "Registry.set(entity, Types.position, velocity.dx, velocity.dy)"
            "});"
            "";

    if(duk_peval_string(ctx, s3)) {
        FAIL();
    }

    ASSERT_EQ(registry.view<duktape_runtime>().size(), 1u);
    ASSERT_EQ(registry.view<position>().size(), 3u);
    ASSERT_EQ(registry.view<renderable>().size(), 2u);

    registry.view<position, renderable, duktape_runtime>().each([](const position &position, auto &&...) {
        ASSERT_EQ(position.x, -100.);
        ASSERT_EQ(position.y, -100.);
    });

    const char *s4 = ""
            "Registry.entities(Types.VELOCITY, Types.PLAYING_CHARACTER).forEach(function(entity) {"
                "Registry.unset(entity, Types.VELOCITY);"
                "Registry.unset(entity, Types.PLAYING_CHARACTER);"
            "});"
            "Registry.entities(Types.position).forEach(function(entity) {"
                "Registry.unset(entity, Types.position);"
            "});"
            "";

    if(duk_peval_string(ctx, s4)) {
        FAIL();
    }

    ASSERT_EQ(registry.view<duktape_runtime>().size(), 0u);
    ASSERT_EQ(registry.view<position>().size(), 0u);
    ASSERT_EQ(registry.view<renderable>().size(), 2u);

    duk_destroy_heap(ctx);
}
<|endoftext|>