<commit_before>/*
 * Copyright (C) 2006, 2007, 2011 Apple Inc. All rights reserved.
 * Copyright (C) 2007-2009 Torch Mobile, Inc.
 *
 * 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.
 *
 * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``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 APPLE COMPUTER, INC. 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.
 */

#include "config.h"
#include "wtf/text/TextEncodingRegistry.h"

#include "wtf/ASCIICType.h"
#include "wtf/CurrentTime.h"
#include "wtf/HashMap.h"
#include "wtf/HashSet.h"
#include "wtf/MainThread.h"
#include "wtf/StdLibExtras.h"
#include "wtf/StringExtras.h"
#include "wtf/ThreadingPrimitives.h"
#include "wtf/text/CString.h"
#include "wtf/text/TextCodecICU.h"
#include "wtf/text/TextCodecLatin1.h"
#include "wtf/text/TextCodecReplacement.h"
#include "wtf/text/TextCodecUTF16.h"
#include "wtf/text/TextCodecUTF8.h"
#include "wtf/text/TextCodecUserDefined.h"
#include "wtf/text/TextEncoding.h"

namespace WTF {

const size_t maxEncodingNameLength = 63;

// Hash for all-ASCII strings that does case folding.
struct TextEncodingNameHash {
    static bool equal(const char* s1, const char* s2)
    {
        char c1;
        char c2;
        do {
#if defined(_MSC_FULL_VER) && _MSC_FULL_VER == 170051106
            // Workaround for a bug in the VS2012 Update 1 optimizer, remove once the fix is released.
            // https://connect.microsoft.com/VisualStudio/feedback/details/777533/vs2012-c-optimizing-bug-when-using-inline-and-char-return-type-x86-target-only
            c1 = toASCIILower(*s1++);
            c2 = toASCIILower(*s2++);
            if (c1 != c2)
                return false;
#else
            c1 = *s1++;
            c2 = *s2++;
            if (toASCIILower(c1) != toASCIILower(c2))
                return false;
#endif
        } while (c1 && c2);
        return !c1 && !c2;
    }

    // This algorithm is the one-at-a-time hash from:
    // http://burtleburtle.net/bob/hash/hashfaq.html
    // http://burtleburtle.net/bob/hash/doobs.html
    static unsigned hash(const char* s)
    {
        unsigned h = WTF::stringHashingStartValue;
        for (;;) {
            char c = *s++;
            if (!c) {
                h += (h << 3);
                h ^= (h >> 11);
                h += (h << 15);
                return h;
            }
            h += toASCIILower(c);
            h += (h << 10);
            h ^= (h >> 6);
        }
    }

    static const bool safeToCompareToEmptyOrDeleted = false;
};

struct TextCodecFactory {
    NewTextCodecFunction function;
    const void* additionalData;
    TextCodecFactory(NewTextCodecFunction f = 0, const void* d = 0) : function(f), additionalData(d) { }
};

typedef HashMap<const char*, const char*, TextEncodingNameHash> TextEncodingNameMap;
typedef HashMap<const char*, TextCodecFactory> TextCodecMap;

static Mutex& encodingRegistryMutex()
{
    // We don't have to use AtomicallyInitializedStatic here because
    // this function is called on the main thread for any page before
    // it is used in worker threads.
    DEFINE_STATIC_LOCAL(Mutex, mutex, ());
    return mutex;
}

static TextEncodingNameMap* textEncodingNameMap;
static TextCodecMap* textCodecMap;
static bool didExtendTextCodecMaps;

static const char textEncodingNameBlacklist[][6] = { "UTF-7" };

#if ERROR_DISABLED

static inline void checkExistingName(const char*, const char*) { }

#else

static void checkExistingName(const char* alias, const char* atomicName)
{
    const char* oldAtomicName = textEncodingNameMap->get(alias);
    if (!oldAtomicName)
        return;
    if (oldAtomicName == atomicName)
        return;
    // Keep the warning silent about one case where we know this will happen.
    if (strcmp(alias, "ISO-8859-8-I") == 0
            && strcmp(oldAtomicName, "ISO-8859-8-I") == 0
            && strcasecmp(atomicName, "iso-8859-8") == 0)
        return;
    WTF_LOG_ERROR("alias %s maps to %s already, but someone is trying to make it map to %s", alias, oldAtomicName, atomicName);
}

#endif

static bool isUndesiredAlias(const char* alias)
{
    // Reject aliases with version numbers that are supported by some back-ends (such as "ISO_2022,locale=ja,version=0" in ICU).
    for (const char* p = alias; *p; ++p) {
        if (*p == ',')
            return true;
    }
    // 8859_1 is known to (at least) ICU, but other browsers don't support this name - and having it caused a compatibility
    // problem, see bug 43554.
    if (0 == strcmp(alias, "8859_1"))
        return true;
    return false;
}

static void addToTextEncodingNameMap(const char* alias, const char* name)
{
    ASSERT(strlen(alias) <= maxEncodingNameLength);
    if (isUndesiredAlias(alias))
        return;
    const char* atomicName = textEncodingNameMap->get(name);
    ASSERT(strcmp(alias, name) == 0 || atomicName);
    if (!atomicName)
        atomicName = name;
    checkExistingName(alias, atomicName);
    textEncodingNameMap->add(alias, atomicName);
}

static void addToTextCodecMap(const char* name, NewTextCodecFunction function, const void* additionalData)
{
    const char* atomicName = textEncodingNameMap->get(name);
    ASSERT(atomicName);
    textCodecMap->add(atomicName, TextCodecFactory(function, additionalData));
}

static void pruneBlacklistedCodecs()
{
    for (size_t i = 0; i < WTF_ARRAY_LENGTH(textEncodingNameBlacklist); ++i) {
        const char* atomicName = textEncodingNameMap->get(textEncodingNameBlacklist[i]);
        if (!atomicName)
            continue;

        Vector<const char*> names;
        TextEncodingNameMap::const_iterator it = textEncodingNameMap->begin();
        TextEncodingNameMap::const_iterator end = textEncodingNameMap->end();
        for (; it != end; ++it) {
            if (it->value == atomicName)
                names.append(it->key);
        }

        textEncodingNameMap->removeAll(names);

        textCodecMap->remove(atomicName);
    }
}

static void buildBaseTextCodecMaps()
{
    ASSERT(isMainThread());
    ASSERT(!textCodecMap);
    ASSERT(!textEncodingNameMap);

    textCodecMap = new TextCodecMap;
    textEncodingNameMap = new TextEncodingNameMap;

    TextCodecLatin1::registerEncodingNames(addToTextEncodingNameMap);
    TextCodecLatin1::registerCodecs(addToTextCodecMap);

    TextCodecUTF8::registerEncodingNames(addToTextEncodingNameMap);
    TextCodecUTF8::registerCodecs(addToTextCodecMap);

    TextCodecUTF16::registerEncodingNames(addToTextEncodingNameMap);
    TextCodecUTF16::registerCodecs(addToTextCodecMap);

    TextCodecUserDefined::registerEncodingNames(addToTextEncodingNameMap);
    TextCodecUserDefined::registerCodecs(addToTextCodecMap);
}

bool isReplacementEncoding(const char* alias)
{
    return alias && !strcasecmp(alias, "replacement");
}

bool isReplacementEncoding(const String& alias)
{
    return alias == "replacement";
}

static void extendTextCodecMaps()
{
    TextCodecReplacement::registerEncodingNames(addToTextEncodingNameMap);
    TextCodecReplacement::registerCodecs(addToTextCodecMap);

    TextCodecICU::registerEncodingNames(addToTextEncodingNameMap);
    TextCodecICU::registerCodecs(addToTextCodecMap);

    pruneBlacklistedCodecs();
}

PassOwnPtr<TextCodec> newTextCodec(const TextEncoding& encoding)
{
    MutexLocker lock(encodingRegistryMutex());

    ASSERT(textCodecMap);
    TextCodecFactory factory = textCodecMap->get(encoding.name());
    ASSERT(factory.function);
    return factory.function(encoding, factory.additionalData);
}

const char* atomicCanonicalTextEncodingName(const char* name)
{
    if (!name || !name[0])
        return 0;
    if (!textEncodingNameMap)
        buildBaseTextCodecMaps();

    MutexLocker lock(encodingRegistryMutex());

    if (const char* atomicName = textEncodingNameMap->get(name))
        return atomicName;
    if (didExtendTextCodecMaps)
        return 0;
    extendTextCodecMaps();
    didExtendTextCodecMaps = true;
    return textEncodingNameMap->get(name);
}

template <typename CharacterType>
const char* atomicCanonicalTextEncodingName(const CharacterType* characters, size_t length)
{
    char buffer[maxEncodingNameLength + 1];
    size_t j = 0;
    for (size_t i = 0; i < length; ++i) {
        char c = static_cast<char>(characters[i]);
        if (j == maxEncodingNameLength || c != characters[i])
            return 0;
        buffer[j++] = c;
    }
    buffer[j] = 0;
    return atomicCanonicalTextEncodingName(buffer);
}

const char* atomicCanonicalTextEncodingName(const String& alias)
{
    if (!alias.length())
        return 0;

    if (alias.is8Bit())
        return atomicCanonicalTextEncodingName<LChar>(alias.characters8(), alias.length());

    return atomicCanonicalTextEncodingName<UChar>(alias.characters16(), alias.length());
}

bool noExtendedTextEncodingNameUsed()
{
    MutexLocker lock(encodingRegistryMutex());
    return !didExtendTextCodecMaps;
}

#ifndef NDEBUG
void dumpTextEncodingNameMap()
{
    unsigned size = textEncodingNameMap->size();
    fprintf(stderr, "Dumping %u entries in WTF::TextEncodingNameMap...\n", size);

    MutexLocker lock(encodingRegistryMutex());

    TextEncodingNameMap::const_iterator it = textEncodingNameMap->begin();
    TextEncodingNameMap::const_iterator end = textEncodingNameMap->end();
    for (; it != end; ++it)
        fprintf(stderr, "'%s' => '%s'\n", it->key, it->value);
}
#endif

} // namespace WTF
<commit_msg>Switched from mutex to atomic op for lazy init check<commit_after>/*
 * Copyright (C) 2006, 2007, 2011 Apple Inc. All rights reserved.
 * Copyright (C) 2007-2009 Torch Mobile, Inc.
 *
 * 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.
 *
 * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``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 APPLE COMPUTER, INC. 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.
 */

#include "config.h"
#include "wtf/text/TextEncodingRegistry.h"

#include "wtf/ASCIICType.h"
#include "wtf/CurrentTime.h"
#include "wtf/HashMap.h"
#include "wtf/HashSet.h"
#include "wtf/MainThread.h"
#include "wtf/StdLibExtras.h"
#include "wtf/StringExtras.h"
#include "wtf/ThreadingPrimitives.h"
#include "wtf/text/CString.h"
#include "wtf/text/TextCodecICU.h"
#include "wtf/text/TextCodecLatin1.h"
#include "wtf/text/TextCodecReplacement.h"
#include "wtf/text/TextCodecUTF16.h"
#include "wtf/text/TextCodecUTF8.h"
#include "wtf/text/TextCodecUserDefined.h"
#include "wtf/text/TextEncoding.h"

namespace WTF {

const size_t maxEncodingNameLength = 63;

// Hash for all-ASCII strings that does case folding.
struct TextEncodingNameHash {
    static bool equal(const char* s1, const char* s2)
    {
        char c1;
        char c2;
        do {
#if defined(_MSC_FULL_VER) && _MSC_FULL_VER == 170051106
            // Workaround for a bug in the VS2012 Update 1 optimizer, remove once the fix is released.
            // https://connect.microsoft.com/VisualStudio/feedback/details/777533/vs2012-c-optimizing-bug-when-using-inline-and-char-return-type-x86-target-only
            c1 = toASCIILower(*s1++);
            c2 = toASCIILower(*s2++);
            if (c1 != c2)
                return false;
#else
            c1 = *s1++;
            c2 = *s2++;
            if (toASCIILower(c1) != toASCIILower(c2))
                return false;
#endif
        } while (c1 && c2);
        return !c1 && !c2;
    }

    // This algorithm is the one-at-a-time hash from:
    // http://burtleburtle.net/bob/hash/hashfaq.html
    // http://burtleburtle.net/bob/hash/doobs.html
    static unsigned hash(const char* s)
    {
        unsigned h = WTF::stringHashingStartValue;
        for (;;) {
            char c = *s++;
            if (!c) {
                h += (h << 3);
                h ^= (h >> 11);
                h += (h << 15);
                return h;
            }
            h += toASCIILower(c);
            h += (h << 10);
            h ^= (h >> 6);
        }
    }

    static const bool safeToCompareToEmptyOrDeleted = false;
};

struct TextCodecFactory {
    NewTextCodecFunction function;
    const void* additionalData;
    TextCodecFactory(NewTextCodecFunction f = 0, const void* d = 0) : function(f), additionalData(d) { }
};

typedef HashMap<const char*, const char*, TextEncodingNameHash> TextEncodingNameMap;
typedef HashMap<const char*, TextCodecFactory> TextCodecMap;

static Mutex& encodingRegistryMutex()
{
    // We don't have to use AtomicallyInitializedStatic here because
    // this function is called on the main thread for any page before
    // it is used in worker threads.
    DEFINE_STATIC_LOCAL(Mutex, mutex, ());
    return mutex;
}

static TextEncodingNameMap* textEncodingNameMap;
static TextCodecMap* textCodecMap;

namespace {
static unsigned didExtendTextCodecMaps = 0;

ALWAYS_INLINE unsigned atomicDidExtendTextCodecMaps()
{
    return acquireLoad(&didExtendTextCodecMaps);
}

ALWAYS_INLINE void atomicSetDidExtendTextCodemMaps()
{
    releaseStore(&didExtendTextCodecMaps, 1);
}
} // namespace

static const char textEncodingNameBlacklist[][6] = { "UTF-7" };

#if ERROR_DISABLED

static inline void checkExistingName(const char*, const char*) { }

#else

static void checkExistingName(const char* alias, const char* atomicName)
{
    const char* oldAtomicName = textEncodingNameMap->get(alias);
    if (!oldAtomicName)
        return;
    if (oldAtomicName == atomicName)
        return;
    // Keep the warning silent about one case where we know this will happen.
    if (strcmp(alias, "ISO-8859-8-I") == 0
            && strcmp(oldAtomicName, "ISO-8859-8-I") == 0
            && strcasecmp(atomicName, "iso-8859-8") == 0)
        return;
    WTF_LOG_ERROR("alias %s maps to %s already, but someone is trying to make it map to %s", alias, oldAtomicName, atomicName);
}

#endif

static bool isUndesiredAlias(const char* alias)
{
    // Reject aliases with version numbers that are supported by some back-ends (such as "ISO_2022,locale=ja,version=0" in ICU).
    for (const char* p = alias; *p; ++p) {
        if (*p == ',')
            return true;
    }
    // 8859_1 is known to (at least) ICU, but other browsers don't support this name - and having it caused a compatibility
    // problem, see bug 43554.
    if (0 == strcmp(alias, "8859_1"))
        return true;
    return false;
}

static void addToTextEncodingNameMap(const char* alias, const char* name)
{
    ASSERT(strlen(alias) <= maxEncodingNameLength);
    if (isUndesiredAlias(alias))
        return;
    const char* atomicName = textEncodingNameMap->get(name);
    ASSERT(strcmp(alias, name) == 0 || atomicName);
    if (!atomicName)
        atomicName = name;
    checkExistingName(alias, atomicName);
    textEncodingNameMap->add(alias, atomicName);
}

static void addToTextCodecMap(const char* name, NewTextCodecFunction function, const void* additionalData)
{
    const char* atomicName = textEncodingNameMap->get(name);
    ASSERT(atomicName);
    textCodecMap->add(atomicName, TextCodecFactory(function, additionalData));
}

static void pruneBlacklistedCodecs()
{
    for (size_t i = 0; i < WTF_ARRAY_LENGTH(textEncodingNameBlacklist); ++i) {
        const char* atomicName = textEncodingNameMap->get(textEncodingNameBlacklist[i]);
        if (!atomicName)
            continue;

        Vector<const char*> names;
        TextEncodingNameMap::const_iterator it = textEncodingNameMap->begin();
        TextEncodingNameMap::const_iterator end = textEncodingNameMap->end();
        for (; it != end; ++it) {
            if (it->value == atomicName)
                names.append(it->key);
        }

        textEncodingNameMap->removeAll(names);

        textCodecMap->remove(atomicName);
    }
}

static void buildBaseTextCodecMaps()
{
    ASSERT(isMainThread());
    ASSERT(!textCodecMap);
    ASSERT(!textEncodingNameMap);

    textCodecMap = new TextCodecMap;
    textEncodingNameMap = new TextEncodingNameMap;

    TextCodecLatin1::registerEncodingNames(addToTextEncodingNameMap);
    TextCodecLatin1::registerCodecs(addToTextCodecMap);

    TextCodecUTF8::registerEncodingNames(addToTextEncodingNameMap);
    TextCodecUTF8::registerCodecs(addToTextCodecMap);

    TextCodecUTF16::registerEncodingNames(addToTextEncodingNameMap);
    TextCodecUTF16::registerCodecs(addToTextCodecMap);

    TextCodecUserDefined::registerEncodingNames(addToTextEncodingNameMap);
    TextCodecUserDefined::registerCodecs(addToTextCodecMap);
}

bool isReplacementEncoding(const char* alias)
{
    return alias && !strcasecmp(alias, "replacement");
}

bool isReplacementEncoding(const String& alias)
{
    return alias == "replacement";
}

static void extendTextCodecMaps()
{
    TextCodecReplacement::registerEncodingNames(addToTextEncodingNameMap);
    TextCodecReplacement::registerCodecs(addToTextCodecMap);

    TextCodecICU::registerEncodingNames(addToTextEncodingNameMap);
    TextCodecICU::registerCodecs(addToTextCodecMap);

    pruneBlacklistedCodecs();
}

PassOwnPtr<TextCodec> newTextCodec(const TextEncoding& encoding)
{
    MutexLocker lock(encodingRegistryMutex());

    ASSERT(textCodecMap);
    TextCodecFactory factory = textCodecMap->get(encoding.name());
    ASSERT(factory.function);
    return factory.function(encoding, factory.additionalData);
}

const char* atomicCanonicalTextEncodingName(const char* name)
{
    if (!name || !name[0])
        return 0;
    if (!textEncodingNameMap)
        buildBaseTextCodecMaps();

    MutexLocker lock(encodingRegistryMutex());

    if (const char* atomicName = textEncodingNameMap->get(name))
        return atomicName;
    if (atomicDidExtendTextCodecMaps())
        return 0;
    extendTextCodecMaps();
    atomicSetDidExtendTextCodemMaps();
    return textEncodingNameMap->get(name);
}

template <typename CharacterType>
const char* atomicCanonicalTextEncodingName(const CharacterType* characters, size_t length)
{
    char buffer[maxEncodingNameLength + 1];
    size_t j = 0;
    for (size_t i = 0; i < length; ++i) {
        char c = static_cast<char>(characters[i]);
        if (j == maxEncodingNameLength || c != characters[i])
            return 0;
        buffer[j++] = c;
    }
    buffer[j] = 0;
    return atomicCanonicalTextEncodingName(buffer);
}

const char* atomicCanonicalTextEncodingName(const String& alias)
{
    if (!alias.length())
        return 0;

    if (alias.is8Bit())
        return atomicCanonicalTextEncodingName<LChar>(alias.characters8(), alias.length());

    return atomicCanonicalTextEncodingName<UChar>(alias.characters16(), alias.length());
}

bool noExtendedTextEncodingNameUsed()
{
    return !atomicDidExtendTextCodecMaps();
}

#ifndef NDEBUG
void dumpTextEncodingNameMap()
{
    unsigned size = textEncodingNameMap->size();
    fprintf(stderr, "Dumping %u entries in WTF::TextEncodingNameMap...\n", size);

    MutexLocker lock(encodingRegistryMutex());

    TextEncodingNameMap::const_iterator it = textEncodingNameMap->begin();
    TextEncodingNameMap::const_iterator end = textEncodingNameMap->end();
    for (; it != end; ++it)
        fprintf(stderr, "'%s' => '%s'\n", it->key, it->value);
}
#endif

} // namespace WTF
<|endoftext|>


<commit_before>// System include(s):
#include <memory>
#include <cstdlib>
#include <iostream>
#include <fstream>
#include <vector>
#include <map>
#include <algorithm>

// ROOT include(s):
#include <TFile.h>
#include <TError.h>
#include <TString.h>
#include <TChain.h>
#include <TH1F.h>
#include <TLorentzVector.h>
#include <TVector2.h>

// Infrastructure include(s):
#ifdef ROOTCORE
#   include "xAODRootAccess/Init.h"
#   include "xAODRootAccess/TEvent.h"
#endif // ROOTCORE

#include "AsgTools/AsgTool.h"
#include "AsgTools/ToolHandle.h"

// EDM include(s):
#include "xAODEventInfo/EventInfo.h"
#include "xAODMuon/MuonContainer.h"
#include "xAODEgamma/ElectronContainer.h"
#include "xAODEgamma/PhotonContainer.h"
#include "xAODTau/TauJetContainer.h"
#include "xAODJet/JetContainer.h"
#include "xAODJet/JetAuxContainer.h"
#include "xAODCaloEvent/CaloCluster.h"
#include "xAODTruth/TruthParticleContainer.h"
#include "xAODTruth/TruthEventContainer.h"
#include "xAODTruth/TruthEvent.h"
#include "xAODTruth/TruthVertex.h"
#include "xAODCore/ShallowCopy.h"
#include "xAODMissingET/MissingETContainer.h"
#include "xAODMissingET/MissingETAuxContainer.h"
#include "xAODBTaggingEfficiency/BTaggingEfficiencyTool.h"
#include "xAODBTaggingEfficiency/BTaggingSelectionTool.h"

#include "xAODBase/IParticleHelpers.h"
#include "xAODTracking/VertexContainer.h"
#include "xAODTracking/TrackParticleContainer.h"

// Local include(s):
#include "CPAnalysisExamples/errorcheck.h"
#include "SUSYTools/SUSYObjDef_xAOD.h"

// Other includes
#include "PATInterfaces/SystematicVariation.h"
#include "PATInterfaces/SystematicRegistry.h"
#include "PATInterfaces/SystematicCode.h"
#include "boost/unordered_map.hpp"

#include "MyXAODTools/EventCounter.h"
#include "MyXAODTools/HZZ4lHelper.h"

using namespace std;

bool descend_on_pt(xAOD::IParticle* p1, xAOD::IParticle* p2){
    return p1->pt() > p2->pt();
}

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

    if(argc > 1 && string(argv[1]) == "help"){
        cout << argv[0] << " toberun.txt num_evts" << endl;
        return 0;
    }
	StatusCode::enableFailure();
	CP::SystematicCode::enableFailure();
	CP::CorrectionCode::enableFailure();

	// The application's name:
	const char* APP_NAME = argv[ 0 ];

	// Initialise the application:
	CHECK( xAOD::Init( APP_NAME ) );
    string inputFileName = "toberun.txt";
    if(argc > 1){
        inputFileName = string(argv[1]);
    }

	TChain* fc = EventCounter::getChain(inputFileName.c_str(), "CollectionTree");

	// Create a TEvent object:
	xAOD::TEvent event( xAOD::TEvent::kClassAccess );
	CHECK( event.readFrom( fc ) );
	Info( APP_NAME, "Number of events in the chain: %i",
			static_cast< int >( event.getEntries() ) );

	// Decide how many events to run over:
	Long64_t entries = event.getEntries();
	if( argc > 2 ) {
		const Long64_t e = atoll( argv[ 2 ] );
		if( e>0 && e < entries ) {
			entries = e;
		}
	}
    Info(APP_NAME, "Will process: %d", (int)entries);

	int RunNumber;
	int EventNumber;
	int mc_channel_number;
	double MCWeight;
    double mc_weight_up;
    double mc_weight_down;
    vector<double>* mc_weights = new vector<double>();

	TFile *fOutputFile = new TFile( "reduced_ntuple.root", "recreate" );
	TTree MyTree( "physics", "physics" );

	MyTree.Branch("RunNumber", &RunNumber, "RunNumber/I");
	MyTree.Branch("EventNumber", &EventNumber, "EventNumber/I");
	MyTree.Branch("mc_channel_number", &mc_channel_number, "mc_channel_number/I");

    unique_ptr<HZZ4lHelper> h4l_helper(new HZZ4lHelper());
    h4l_helper->MakeOutputTree(MyTree);
    h4l_helper->MakeTruthTree(MyTree);

    int type;
    MyTree.Branch("truth_event_type", &type, "truth_event_type/I");
    int truth_type;
    MyTree.Branch("type_truth", &truth_type, "type_truth/I");

	MyTree.Branch("MCWeight", &MCWeight, "MCWeight/D");
	MyTree.Branch("MCWeightUp", &mc_weight_up, "MCWeightUp/D");
	MyTree.Branch("MCWeightDown", &mc_weight_down, "MCWeightDown/D");
	MyTree.Branch("MCWeights", &mc_weights);

    // add jet information
    double dijet_invmass = -999;
    double dijet_deltaeta = -999;
	MyTree.Branch("dijet_deltaeta_fid", &dijet_deltaeta, "dijet_deltaeta_fid/D");
	MyTree.Branch("dijet_invmass_fid", &dijet_invmass, "dijet_invmass_fid/D");

    int pass_fid = -1;
    MyTree.Branch("pass_fid_cut", &pass_fid, "pass_fid_cut/I");
    int pass_fid_truth = -1;
    MyTree.Branch("pass_fid_cut_truth", &pass_fid_truth, "pass_fid_cut_truth/I");

	for( Long64_t entry = 0; entry < entries; ++entry ) {

        mc_weights->clear();
        h4l_helper->Clear();
        dijet_invmass = -999;
        dijet_deltaeta = -999;
        pass_fid = -1;
        type = -1;
        truth_type = -1;

		// Tell the object which entry to look at:
		event.getEntry( entry );

		const xAOD::EventInfo* ei = 0;
		CHECK( event.retrieve( ei, "EventInfo" ) );

		RunNumber = ei->runNumber();
		EventNumber = ei->eventNumber();
		mc_channel_number = ei-> mcChannelNumber();

		MCWeight = ei->mcEventWeight();

        const vector<float>& weights = ei->mcEventWeights();
        if(weights.size() > 2) {
            mc_weight_up = weights.at(1);
            mc_weight_down = weights.at(2);
        }
        for(int i = 0; i < (int)weights.size(); i ++){
            mc_weights->push_back(weights.at(i));
        }

		// Get the Jets from the event:
		const xAOD::JetContainer* jets_origin = 0;
        CHECK( event.retrieve( jets_origin, "AntiKt4TruthJets" ) );
        std::pair<xAOD::JetContainer*, xAOD::ShallowAuxContainer*> jet_shallowcopy = xAOD::shallowCopyContainer(*jets_origin);
        xAOD::JetContainer* jets = jet_shallowcopy.first;

        // calculate dijet invariant mass and delta-eta
        if (jets->size() >= 2){
            sort(jets->begin(), jets->end(), descend_on_pt);
            dijet_invmass = (jets->at(0)->p4() + jets->at(1)->p4()).M();
            dijet_deltaeta = fabs(jets->at(0)->eta() - jets->at(1)->eta());
        }

        // get truth info
       const xAOD::TruthParticleContainer* particles(0);
       if( event.retrieve(particles, "TruthParticles").isSuccess() )
       {
           // get truth information
           h4l_helper->GetTruthInfo( *particles );
           truth_type = h4l_helper->getTruthType();
       } else {
           cout << "No truth particles" << endl;
       }

        ////get electrons and muons, then to mimic our fiducial selection
        const xAOD::TruthParticleContainer* electrons(0);
        const xAOD::TruthParticleContainer* muons(0);
        CHECK( event.retrieve(muons, "TruthMuons") );
        if( ! event.retrieve(electrons,"TruthElectrons").isSuccess() ||
            ! event.retrieve(muons, "TruthMuons").isSuccess() )
        {
            if (entry == 0){
                cout << "Cannot find TruthMuons or TruthElectrons" << endl;
            }
            continue;
        }
        xAOD::TruthParticleContainer::const_iterator ele_itr = electrons->begin();
        xAOD::TruthParticleContainer::const_iterator ele_end = electrons->end();

        vector<Candidate*>* ele_4vec = new vector<Candidate*>();
        int ele_index = 0;
        for(; ele_itr != ele_end; ele_itr ++){
            if( (*ele_itr)->status() == 1 && (*ele_itr)->absPdgId() == 11)
            {
                TLorentzVector ele;
                ele.SetPxPyPzE((*ele_itr)->px(),(*ele_itr)->py(),
                        (*ele_itr)->pz(), (*ele_itr)->e());
                if(ele.Pt() > 7e3 && ele.Eta() < 2.47){
                    float charge = (*ele_itr)->pdgId()/11.;
                    Candidate* can = new Candidate(ele_index, ele);
                    can->setCharge(charge);
                    ele_4vec ->push_back(can);
                }
            }
            ele_index ++;
        }
        // Info(APP_NAME, "Number of electrons: %d", (int)ele_4vec->size());

        xAOD::TruthParticleContainer::const_iterator muon_itr = muons->begin();
        xAOD::TruthParticleContainer::const_iterator muon_end = muons->end();
        // cout << "total muons: " << muons->size() << endl;
        vector<Candidate*>* muon_4vec = new vector<Candidate*>();
        int index = 0;
        for(; muon_itr != muon_end; muon_itr++){
            if( (*muon_itr)->status() == 1 && (*muon_itr)->absPdgId() == 13)
            {
                TLorentzVector mu ;
                mu.SetPxPyPzE((*muon_itr)->px(), (*muon_itr)->py(),
                        (*muon_itr)->pz(), (*muon_itr)->e());
                if(mu.Pt() > 5e3 && mu.Eta() < 2.7){
                    float charge = (*muon_itr)->pdgId()/13.;
                    Candidate* can = new Candidate(index, mu);
                    can->setCharge(charge);
                    muon_4vec->push_back(can);
                }
            }
            index ++;
        }
        // Info(APP_NAME, "Number of muons: %d", (int)muon_4vec->size());

        if(ele_4vec->size() >= 4 && h4l_helper->Is_4mu4e(ele_4vec)){
            type = 1; //4electrons
        }else if(muon_4vec->size() >= 4 && h4l_helper->Is_4mu4e(muon_4vec)){
            type = 0; //4muons
        }else if (ele_4vec->size() >=2 && muon_4vec->size() >= 2){
            h4l_helper->Is_2e2mu(ele_4vec, muon_4vec, type);
        }else{
            type = -1;
        }
        h4l_helper->setType(type);

        pass_fid = h4l_helper->passFiducial();
        pass_fid_truth = h4l_helper->passFiducialTruth();

        MyTree.Fill();
        for(int i =0; i < (int)ele_4vec->size(); i++){
            delete ele_4vec->at(i);
        }
        delete ele_4vec;
        for(int i = 0; i < (int)muon_4vec->size(); i++){
            delete muon_4vec->at(i);
        }
        delete muon_4vec;
    }
    delete mc_weights;

    fOutputFile->cd();
    MyTree.Write();
    fOutputFile->Close();

    Info( APP_NAME, "Successfully finished analysis; Exitting..." );
    return 1;
}
<commit_msg>add jet pt and eta cuts<commit_after>// System include(s):
#include <memory>
#include <cstdlib>
#include <iostream>
#include <fstream>
#include <vector>
#include <map>
#include <algorithm>

// ROOT include(s):
#include <TFile.h>
#include <TError.h>
#include <TString.h>
#include <TChain.h>
#include <TH1F.h>
#include <TLorentzVector.h>
#include <TVector2.h>

// Infrastructure include(s):
#ifdef ROOTCORE
#   include "xAODRootAccess/Init.h"
#   include "xAODRootAccess/TEvent.h"
#endif // ROOTCORE

#include "AsgTools/AsgTool.h"
#include "AsgTools/ToolHandle.h"

// EDM include(s):
#include "xAODEventInfo/EventInfo.h"
#include "xAODMuon/MuonContainer.h"
#include "xAODEgamma/ElectronContainer.h"
#include "xAODEgamma/PhotonContainer.h"
#include "xAODTau/TauJetContainer.h"
#include "xAODJet/JetContainer.h"
#include "xAODJet/JetAuxContainer.h"
#include "xAODCaloEvent/CaloCluster.h"
#include "xAODTruth/TruthParticleContainer.h"
#include "xAODTruth/TruthEventContainer.h"
#include "xAODTruth/TruthEvent.h"
#include "xAODTruth/TruthVertex.h"
#include "xAODCore/ShallowCopy.h"
#include "xAODMissingET/MissingETContainer.h"
#include "xAODMissingET/MissingETAuxContainer.h"
#include "xAODBTaggingEfficiency/BTaggingEfficiencyTool.h"
#include "xAODBTaggingEfficiency/BTaggingSelectionTool.h"

#include "xAODBase/IParticleHelpers.h"
#include "xAODTracking/VertexContainer.h"
#include "xAODTracking/TrackParticleContainer.h"

// Local include(s):
#include "CPAnalysisExamples/errorcheck.h"
#include "SUSYTools/SUSYObjDef_xAOD.h"

// Other includes
#include "PATInterfaces/SystematicVariation.h"
#include "PATInterfaces/SystematicRegistry.h"
#include "PATInterfaces/SystematicCode.h"
#include "boost/unordered_map.hpp"

#include "MyXAODTools/EventCounter.h"
#include "MyXAODTools/HZZ4lHelper.h"

using namespace std;

bool descend_on_pt(xAOD::IParticle* p1, xAOD::IParticle* p2){
    return p1->pt() > p2->pt();
}

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

    if(argc > 1 && string(argv[1]) == "help"){
        cout << argv[0] << " toberun.txt num_evts" << endl;
        return 0;
    }
	StatusCode::enableFailure();
	CP::SystematicCode::enableFailure();
	CP::CorrectionCode::enableFailure();

	// The application's name:
	const char* APP_NAME = argv[ 0 ];

	// Initialise the application:
	CHECK( xAOD::Init( APP_NAME ) );
    string inputFileName = "toberun.txt";
    if(argc > 1){
        inputFileName = string(argv[1]);
    }

	TChain* fc = EventCounter::getChain(inputFileName.c_str(), "CollectionTree");

	// Create a TEvent object:
	xAOD::TEvent event( xAOD::TEvent::kClassAccess );
	CHECK( event.readFrom( fc ) );
	Info( APP_NAME, "Number of events in the chain: %i",
			static_cast< int >( event.getEntries() ) );

	// Decide how many events to run over:
	Long64_t entries = event.getEntries();
	if( argc > 2 ) {
		const Long64_t e = atoll( argv[ 2 ] );
		if( e>0 && e < entries ) {
			entries = e;
		}
	}
    Info(APP_NAME, "Will process: %d", (int)entries);

	int RunNumber;
	int EventNumber;
	int mc_channel_number;
	double MCWeight;
    double mc_weight_up;
    double mc_weight_down;
    vector<double>* mc_weights = new vector<double>();

	TFile *fOutputFile = new TFile( "reduced_ntuple.root", "recreate" );
	TTree MyTree( "physics", "physics" );

	MyTree.Branch("RunNumber", &RunNumber, "RunNumber/I");
	MyTree.Branch("EventNumber", &EventNumber, "EventNumber/I");
	MyTree.Branch("mc_channel_number", &mc_channel_number, "mc_channel_number/I");

    unique_ptr<HZZ4lHelper> h4l_helper(new HZZ4lHelper());
    h4l_helper->MakeOutputTree(MyTree);
    h4l_helper->MakeTruthTree(MyTree);

    int type;
    MyTree.Branch("truth_event_type", &type, "truth_event_type/I");
    int truth_type;
    MyTree.Branch("type_truth", &truth_type, "type_truth/I");

	MyTree.Branch("MCWeight", &MCWeight, "MCWeight/D");
	MyTree.Branch("MCWeightUp", &mc_weight_up, "MCWeightUp/D");
	MyTree.Branch("MCWeightDown", &mc_weight_down, "MCWeightDown/D");
	MyTree.Branch("MCWeights", &mc_weights);

    // add jet information
    double dijet_invmass = -999;
    double dijet_deltaeta = -999;
	MyTree.Branch("dijet_deltaeta_fid", &dijet_deltaeta, "dijet_deltaeta_fid/D");
	MyTree.Branch("dijet_invmass_fid", &dijet_invmass, "dijet_invmass_fid/D");

    int pass_fid = -1;
    MyTree.Branch("pass_fid_cut", &pass_fid, "pass_fid_cut/I");
    int pass_fid_truth = -1;
    MyTree.Branch("pass_fid_cut_truth", &pass_fid_truth, "pass_fid_cut_truth/I");

	for( Long64_t entry = 0; entry < entries; ++entry ) {

        mc_weights->clear();
        h4l_helper->Clear();
        dijet_invmass = -999;
        dijet_deltaeta = -999;
        pass_fid = -1;
        type = -1;
        truth_type = -1;

		// Tell the object which entry to look at:
		event.getEntry( entry );

		const xAOD::EventInfo* ei = 0;
		CHECK( event.retrieve( ei, "EventInfo" ) );

		RunNumber = ei->runNumber();
		EventNumber = ei->eventNumber();
		mc_channel_number = ei-> mcChannelNumber();

		MCWeight = ei->mcEventWeight();

        const vector<float>& weights = ei->mcEventWeights();
        if(weights.size() > 2) {
            mc_weight_up = weights.at(1);
            mc_weight_down = weights.at(2);
        }
        for(int i = 0; i < (int)weights.size(); i ++){
            mc_weights->push_back(weights.at(i));
        }

		// Get the Jets from the event:
		const xAOD::JetContainer* jets_origin = 0;
        CHECK( event.retrieve( jets_origin, "AntiKt4TruthJets" ) );
        std::pair<xAOD::JetContainer*, xAOD::ShallowAuxContainer*> jet_shallowcopy = xAOD::shallowCopyContainer(*jets_origin);
        xAOD::JetContainer* jets = jet_shallowcopy.first;

        // calculate dijet invariant mass and delta-eta
        if (jets->size() >= 2){
            sort(jets->begin(), jets->end(), descend_on_pt);
            if(jets->at(1)->p4().Pt()/1E3 > 30
               && fabs(jets->at(0)->p4().Eta()) < 4.5
               && fabs(jets->at(1)->p4().Eta()) < 4.5
               ){
                dijet_invmass = (jets->at(0)->p4() + jets->at(1)->p4()).M();
                dijet_deltaeta = fabs(jets->at(0)->eta() - jets->at(1)->eta());
            }
        }

        // get truth info
       const xAOD::TruthParticleContainer* particles(0);
       if( event.retrieve(particles, "TruthParticles").isSuccess() )
       {
           // get truth information
           h4l_helper->GetTruthInfo( *particles );
           truth_type = h4l_helper->getTruthType();
       } else {
           cout << "No truth particles" << endl;
       }

        ////get electrons and muons, then to mimic our fiducial selection
        const xAOD::TruthParticleContainer* electrons(0);
        const xAOD::TruthParticleContainer* muons(0);
        CHECK( event.retrieve(muons, "TruthMuons") );
        if( ! event.retrieve(electrons,"TruthElectrons").isSuccess() ||
            ! event.retrieve(muons, "TruthMuons").isSuccess() )
        {
            if (entry == 0){
                cout << "Cannot find TruthMuons or TruthElectrons" << endl;
            }
            continue;
        }
        xAOD::TruthParticleContainer::const_iterator ele_itr = electrons->begin();
        xAOD::TruthParticleContainer::const_iterator ele_end = electrons->end();

        vector<Candidate*>* ele_4vec = new vector<Candidate*>();
        int ele_index = 0;
        for(; ele_itr != ele_end; ele_itr ++){
            if( (*ele_itr)->status() == 1 && (*ele_itr)->absPdgId() == 11)
            {
                TLorentzVector ele;
                ele.SetPxPyPzE((*ele_itr)->px(),(*ele_itr)->py(),
                        (*ele_itr)->pz(), (*ele_itr)->e());
                if(ele.Pt() > 7e3 && ele.Eta() < 2.47){
                    float charge = (*ele_itr)->pdgId()/11.;
                    Candidate* can = new Candidate(ele_index, ele);
                    can->setCharge(charge);
                    ele_4vec ->push_back(can);
                }
            }
            ele_index ++;
        }
        // Info(APP_NAME, "Number of electrons: %d", (int)ele_4vec->size());

        xAOD::TruthParticleContainer::const_iterator muon_itr = muons->begin();
        xAOD::TruthParticleContainer::const_iterator muon_end = muons->end();
        // cout << "total muons: " << muons->size() << endl;
        vector<Candidate*>* muon_4vec = new vector<Candidate*>();
        int index = 0;
        for(; muon_itr != muon_end; muon_itr++){
            if( (*muon_itr)->status() == 1 && (*muon_itr)->absPdgId() == 13)
            {
                TLorentzVector mu ;
                mu.SetPxPyPzE((*muon_itr)->px(), (*muon_itr)->py(),
                        (*muon_itr)->pz(), (*muon_itr)->e());
                if(mu.Pt() > 5e3 && mu.Eta() < 2.7){
                    float charge = (*muon_itr)->pdgId()/13.;
                    Candidate* can = new Candidate(index, mu);
                    can->setCharge(charge);
                    muon_4vec->push_back(can);
                }
            }
            index ++;
        }
        // Info(APP_NAME, "Number of muons: %d", (int)muon_4vec->size());

        if(ele_4vec->size() >= 4 && h4l_helper->Is_4mu4e(ele_4vec)){
            type = 1; //4electrons
        }else if(muon_4vec->size() >= 4 && h4l_helper->Is_4mu4e(muon_4vec)){
            type = 0; //4muons
        }else if (ele_4vec->size() >=2 && muon_4vec->size() >= 2){
            h4l_helper->Is_2e2mu(ele_4vec, muon_4vec, type);
        }else{
            type = -1;
        }
        h4l_helper->setType(type);

        pass_fid = h4l_helper->passFiducial();
        pass_fid_truth = h4l_helper->passFiducialTruth();

        MyTree.Fill();
        for(int i =0; i < (int)ele_4vec->size(); i++){
            delete ele_4vec->at(i);
        }
        delete ele_4vec;
        for(int i = 0; i < (int)muon_4vec->size(); i++){
            delete muon_4vec->at(i);
        }
        delete muon_4vec;
    }
    delete mc_weights;

    fOutputFile->cd();
    MyTree.Write();
    fOutputFile->Close();

    Info( APP_NAME, "Successfully finished analysis; Exitting..." );
    return 1;
}
<|endoftext|>


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

#include <cmath>
#include <iostream>
#include <memory>
#include <mutex>

#include "host.hpp"

std::unique_ptr<Sensor> HostSensor::CreateTemp(
    const std::string& name,
    int64_t timeout,
    sdbusplus::bus::bus& bus,
    const char* objPath,
    bool defer)
{
    auto sensor = std::make_unique<HostSensor>(name, timeout, bus, objPath, defer);
    sensor->value(0);

    // TODO(venture): Need to not hard-code that this is DegreesC and scale
    // 10x-3 unless it is! :D
    sensor->unit(ValueInterface::Unit::DegreesC);
    sensor->scale(-3);
    sensor->emit_object_added();

    /* TODO(venture): Need to set that _updated is set to epoch or something
     * else.  what is the default value?
     */
    return sensor;
}

int64_t HostSensor::value(int64_t value)
{
    std::lock_guard<std::mutex> guard(_lock);

    _updated = std::chrono::high_resolution_clock::now();
    _value = value * pow(10, scale()); /* scale value */

    return ValueObject::value(value);
}

ReadReturn HostSensor::read(void)
{
    std::lock_guard<std::mutex> guard(_lock);

    /* This doesn't sanity check anything, that's the caller's job. */
    struct ReadReturn r = {
        _value,
        _updated
    };

    return r;
}

void HostSensor::write(double value)
{
    throw std::runtime_error("Not Implemented.");
}

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

#include <cmath>
#include <iostream>
#include <memory>
#include <mutex>

#include "host.hpp"

std::unique_ptr<Sensor> HostSensor::CreateTemp(
    const std::string& name,
    int64_t timeout,
    sdbusplus::bus::bus& bus,
    const char* objPath,
    bool defer)
{
    auto sensor = std::make_unique<HostSensor>(name, timeout, bus, objPath, defer);
    sensor->value(0);

    // DegreesC and value of 0 are the defaults at present, therefore testing
    // this code only sees scale get updated as a property.

    // TODO(venture): Need to not hard-code that this is DegreesC and scale
    // 10x-3 unless it is! :D
    sensor->unit(ValueInterface::Unit::DegreesC);
    sensor->scale(-3);
    sensor->emit_object_added();
    // emit_object_added() can be called twice, harmlessly, the second time it
    // doesn't actually happen, but we don't want to call it before we set up
    // the initial values, so we should not let someone call this with
    // defer=false.

    /* TODO(venture): Need to set that _updated is set to epoch or something
     * else.  what is the default value?
     */
    return sensor;
}

int64_t HostSensor::value(int64_t value)
{
    std::lock_guard<std::mutex> guard(_lock);

    _updated = std::chrono::high_resolution_clock::now();
    _value = value * pow(10, scale()); /* scale value */

    return ValueObject::value(value);
}

ReadReturn HostSensor::read(void)
{
    std::lock_guard<std::mutex> guard(_lock);

    /* This doesn't sanity check anything, that's the caller's job. */
    struct ReadReturn r = {
        _value,
        _updated
    };

    return r;
}

void HostSensor::write(double value)
{
    throw std::runtime_error("Not Implemented.");
}

<|endoftext|>


<commit_before>#define MS_CLASS "RTC::PlainRtpTransport"
// #define MS_LOG_DEV

#include "RTC/PlainRtpTransport.hpp"
#include "DepLibUV.hpp"
#include "Logger.hpp"
#include "MediaSoupError.hpp"
#include "Settings.hpp"
#include "Utils.hpp"
#include "RTC/Consumer.hpp"
#include "RTC/Producer.hpp"

namespace RTC
{
	/* Instance methods. */

	PlainRtpTransport::PlainRtpTransport(
	  RTC::Transport::Listener* listener,
	  Channel::Notifier* notifier,
	  uint32_t transportId,
	  Options& options)
	  : RTC::Transport::Transport(listener, notifier, transportId)
	{
		MS_TRACE();

		// Remote IP address is provided.
		if (!options.remoteIP.empty())
		{
			int addressFamily = Utils::IP::GetFamily(options.remoteIP);

			if (addressFamily == AF_INET)
				CreateSocket(AF_INET, options.localIP);
			else if (addressFamily == AF_INET6)
				CreateSocket(AF_INET6, options.localIP);
			else
				MS_THROW_ERROR("invalid destination IP '%s'", options.remoteIP.c_str());

			// This may throw.
			try
			{
				SetRemoteParameters(options.remoteIP.c_str(), options.remotePort);
			}
			catch (const MediaSoupError& error)
			{
				// Destroy UdpSocket since ~PlainRtpTransport() will not be called.
				this->udpSocket->Destroy();

				throw;
			}
		}
		// No remote IP address is provided.
		else
		{
			// IPv4 is preferred.
			if (options.preferIPv4)
			{
				if (!Settings::configuration.hasIPv4)
					MS_THROW_ERROR("IPv4 disabled");

				CreateSocket(AF_INET, options.localIP);
			}
			// IPv6 is preferred.
			else if (options.preferIPv6)
			{
				if (!Settings::configuration.hasIPv6)
					MS_THROW_ERROR("IPv6 disabled");

				CreateSocket(AF_INET6, options.localIP);
			}
			// No IP family preference, try with IPv4 and then IPv6.
			else if (Settings::configuration.hasIPv4)
			{
				CreateSocket(AF_INET, options.localIP);
			}
			else
			{
				CreateSocket(AF_INET6, options.localIP);
			}
		}
	}

	PlainRtpTransport::~PlainRtpTransport()
	{
		MS_TRACE();

		if (this->tuple != nullptr)
			delete this->tuple;

		if (this->udpSocket != nullptr)
			this->udpSocket->Destroy();
	}

	Json::Value PlainRtpTransport::ToJson() const
	{
		MS_TRACE();

		static const Json::StaticString JsonStringTransportId{ "transportId" };
		static const Json::StaticString JsonStringTuple{ "tuple" };
		static const Json::StaticString JsonStringRtpListener{ "rtpListener" };
		static const Json::StaticString JsonStringLocalIP{ "localIP" };
		static const Json::StaticString JsonStringLocalPort{ "localPort" };

		Json::Value json(Json::objectValue);

		// Add transportId.
		json[JsonStringTransportId] = Json::UInt{ this->transportId };

		// Add tuple.
		if (this->tuple != nullptr)
			json[JsonStringTuple] = this->tuple->ToJson();

		// Local IP address and port.
		json[JsonStringLocalIP]   = this->udpSocket->GetLocalIP();
		json[JsonStringLocalPort] = Json::UInt{ this->udpSocket->GetLocalPort() };

		// Add rtpListener.
		json[JsonStringRtpListener] = this->rtpListener.ToJson();

		return json;
	}

	Json::Value PlainRtpTransport::GetStats() const
	{
		MS_TRACE();

		Json::Value json(Json::objectValue);

		return json;
	}

	void PlainRtpTransport::SetRemoteParameters(const std::string& ip, const uint16_t port)
	{
		int err;

		switch (Utils::IP::GetFamily(ip))
		{
			case AF_INET:
			{
				if (!Settings::configuration.hasIPv4)
					MS_THROW_ERROR("IPv4 disabled");

				err = uv_ip4_addr(
				  ip.c_str(),
				  static_cast<int>(port),
				  reinterpret_cast<struct sockaddr_in*>(&this->remoteAddrStorage));
				if (err != 0)
					MS_ABORT("uv_ipv4_addr() failed: %s", uv_strerror(err));

				break;
			}

			case AF_INET6:
			{
				if (!Settings::configuration.hasIPv6)
					MS_THROW_ERROR("IPv6 disabled");

				err = uv_ip6_addr(
				  ip.c_str(),
				  static_cast<int>(port),
				  reinterpret_cast<struct sockaddr_in6*>(&this->remoteAddrStorage));
				if (err != 0)
					MS_ABORT("uv_ipv6_addr() failed: %s", uv_strerror(err));

				break;
			}

			default:
			{
				MS_THROW_ERROR("invalid destination IP '%s'", ip.c_str());

				break;
			}
		}

		// Create a single tuple.
		this->tuple = new RTC::TransportTuple(
		  this->udpSocket, reinterpret_cast<struct sockaddr*>(&this->remoteAddrStorage));

		// Start the RTCP timer.
		this->rtcpTimer->Start(static_cast<uint64_t>(RTC::RTCP::MaxVideoIntervalMs / 2));
	}

	void PlainRtpTransport::SendRtpPacket(RTC::RtpPacket* packet)
	{
		MS_TRACE();

		if (!IsConnected())
			return;

		const uint8_t* data = packet->GetData();
		size_t len          = packet->GetSize();

		// Mirror RTP if needed.
		if (this->mirrorTuple != nullptr && this->mirroringOptions.sendRtp)
			this->mirrorTuple->Send(data, len);

		this->tuple->Send(data, len);
	}

	void PlainRtpTransport::SendRtcpPacket(RTC::RTCP::Packet* packet)
	{
		MS_TRACE();

		if (!IsConnected())
			return;

		const uint8_t* data = packet->GetData();
		size_t len          = packet->GetSize();

		// Mirror RTCP if needed.
		if (this->mirrorTuple != nullptr && this->mirroringOptions.sendRtcp)
			this->mirrorTuple->Send(data, len);

		this->tuple->Send(data, len);
	}

	void PlainRtpTransport::CreateSocket(int addressFamily, const std::string& localIP)
	{
		if (localIP.empty())
			this->udpSocket = new RTC::UdpSocket(this, addressFamily);
		else
			this->udpSocket = new RTC::UdpSocket(this, localIP);
	}

	bool PlainRtpTransport::IsConnected() const
	{
		return this->tuple ? true : false;
	}

	void PlainRtpTransport::SendRtcpCompoundPacket(RTC::RTCP::CompoundPacket* packet)
	{
		MS_TRACE();

		if (!IsConnected())
			return;

		const uint8_t* data = packet->GetData();
		size_t len          = packet->GetSize();

		// Mirror RTCP if needed.
		if (this->mirrorTuple != nullptr && this->mirroringOptions.sendRtcp)
			this->mirrorTuple->Send(data, len);

		this->tuple->Send(data, len);
	}

	inline void PlainRtpTransport::OnPacketRecv(RTC::TransportTuple* tuple, const uint8_t* data, size_t len)
	{
		MS_TRACE();

		// Check if it's RTCP.
		if (RTCP::Packet::IsRtcp(data, len))
		{
			OnRtcpDataRecv(tuple, data, len);
		}
		// Check if it's RTP.
		else if (RtpPacket::IsRtp(data, len))
		{
			OnRtpDataRecv(tuple, data, len);
		}
		else
		{
			MS_WARN_DEV("ignoring received packet of unknown type");
		}
	}

	inline void PlainRtpTransport::OnRtpDataRecv(
	  RTC::TransportTuple* /*tuple*/, const uint8_t* data, size_t len)
	{
		MS_TRACE();

		// Mirror RTP if needed.
		if (this->mirrorTuple != nullptr && this->mirroringOptions.recvRtp)
			this->mirrorTuple->Send(data, len);

		RTC::RtpPacket* packet = RTC::RtpPacket::Parse(data, len);

		if (packet == nullptr)
		{
			MS_WARN_TAG(rtp, "received data is not a valid RTP packet");

			return;
		}

		// Apply the Transport RTP header extension ids so the RTP listener can use them.

		if (this->headerExtensionIds.rid != 0u)
		{
			packet->AddExtensionMapping(
			  RtpHeaderExtensionUri::Type::RTP_STREAM_ID, this->headerExtensionIds.rid);
		}
		if (this->headerExtensionIds.absSendTime != 0u)
		{
			packet->AddExtensionMapping(
			  RtpHeaderExtensionUri::Type::ABS_SEND_TIME, this->headerExtensionIds.absSendTime);
		}

		// Get the associated Producer.
		RTC::Producer* producer = this->rtpListener.GetProducer(packet);

		if (producer == nullptr)
		{
			MS_WARN_TAG(
			  rtp,
			  "no suitable Producer for received RTP packet [ssrc:%" PRIu32 ", payloadType:%" PRIu8 "]",
			  packet->GetSsrc(),
			  packet->GetPayloadType());

			delete packet;
			return;
		}

		MS_DEBUG_DEV(
		  "RTP packet received [ssrc:%" PRIu32 ", payloadType:%" PRIu8 ", producer:%" PRIu32 "]",
		  packet->GetSsrc(),
		  packet->GetPayloadType(),
		  producer->producerId);

		// Pass the RTP packet to the corresponding Producer.
		producer->ReceiveRtpPacket(packet);

		delete packet;
	}

	inline void PlainRtpTransport::OnRtcpDataRecv(
	  RTC::TransportTuple* /*tuple*/, const uint8_t* data, size_t len)
	{
		MS_TRACE();

		// Mirror RTCP if needed.
		if (this->mirrorTuple != nullptr && this->mirroringOptions.recvRtcp)
			this->mirrorTuple->Send(data, len);

		RTC::RTCP::Packet* packet = RTC::RTCP::Packet::Parse(data, len);

		if (packet == nullptr)
		{
			MS_WARN_TAG(rtcp, "received data is not a valid RTCP compound or single packet");

			return;
		}

		// Handle each RTCP packet.
		while (packet != nullptr)
		{
			HandleRtcpPacket(packet);

			RTC::RTCP::Packet* previousPacket = packet;

			packet = packet->GetNext();
			delete previousPacket;
		}
	}

	void PlainRtpTransport::OnPacketRecv(
	  RTC::UdpSocket* socket, const uint8_t* data, size_t len, const struct sockaddr* remoteAddr)
	{
		MS_TRACE();

		RTC::TransportTuple tuple(socket, remoteAddr);

		OnPacketRecv(&tuple, data, len);
	}
} // namespace RTC
<commit_msg>PlainRtpTransport: don't pass the result of c_str() to a function that takes std::string as argument<commit_after>#define MS_CLASS "RTC::PlainRtpTransport"
// #define MS_LOG_DEV

#include "RTC/PlainRtpTransport.hpp"
#include "DepLibUV.hpp"
#include "Logger.hpp"
#include "MediaSoupError.hpp"
#include "Settings.hpp"
#include "Utils.hpp"
#include "RTC/Consumer.hpp"
#include "RTC/Producer.hpp"

namespace RTC
{
	/* Instance methods. */

	PlainRtpTransport::PlainRtpTransport(
	  RTC::Transport::Listener* listener,
	  Channel::Notifier* notifier,
	  uint32_t transportId,
	  Options& options)
	  : RTC::Transport::Transport(listener, notifier, transportId)
	{
		MS_TRACE();

		// Remote IP address is provided.
		if (!options.remoteIP.empty())
		{
			int addressFamily = Utils::IP::GetFamily(options.remoteIP);

			if (addressFamily == AF_INET)
				CreateSocket(AF_INET, options.localIP);
			else if (addressFamily == AF_INET6)
				CreateSocket(AF_INET6, options.localIP);
			else
				MS_THROW_ERROR("invalid destination IP '%s'", options.remoteIP.c_str());

			// This may throw.
			try
			{
				SetRemoteParameters(options.remoteIP, options.remotePort);
			}
			catch (const MediaSoupError& error)
			{
				// Destroy UdpSocket since ~PlainRtpTransport() will not be called.
				this->udpSocket->Destroy();

				throw;
			}
		}
		// No remote IP address is provided.
		else
		{
			// IPv4 is preferred.
			if (options.preferIPv4)
			{
				if (!Settings::configuration.hasIPv4)
					MS_THROW_ERROR("IPv4 disabled");

				CreateSocket(AF_INET, options.localIP);
			}
			// IPv6 is preferred.
			else if (options.preferIPv6)
			{
				if (!Settings::configuration.hasIPv6)
					MS_THROW_ERROR("IPv6 disabled");

				CreateSocket(AF_INET6, options.localIP);
			}
			// No IP family preference, try with IPv4 and then IPv6.
			else if (Settings::configuration.hasIPv4)
			{
				CreateSocket(AF_INET, options.localIP);
			}
			else
			{
				CreateSocket(AF_INET6, options.localIP);
			}
		}
	}

	PlainRtpTransport::~PlainRtpTransport()
	{
		MS_TRACE();

		if (this->tuple != nullptr)
			delete this->tuple;

		if (this->udpSocket != nullptr)
			this->udpSocket->Destroy();
	}

	Json::Value PlainRtpTransport::ToJson() const
	{
		MS_TRACE();

		static const Json::StaticString JsonStringTransportId{ "transportId" };
		static const Json::StaticString JsonStringTuple{ "tuple" };
		static const Json::StaticString JsonStringRtpListener{ "rtpListener" };
		static const Json::StaticString JsonStringLocalIP{ "localIP" };
		static const Json::StaticString JsonStringLocalPort{ "localPort" };

		Json::Value json(Json::objectValue);

		// Add transportId.
		json[JsonStringTransportId] = Json::UInt{ this->transportId };

		// Add tuple.
		if (this->tuple != nullptr)
			json[JsonStringTuple] = this->tuple->ToJson();

		// Local IP address and port.
		json[JsonStringLocalIP]   = this->udpSocket->GetLocalIP();
		json[JsonStringLocalPort] = Json::UInt{ this->udpSocket->GetLocalPort() };

		// Add rtpListener.
		json[JsonStringRtpListener] = this->rtpListener.ToJson();

		return json;
	}

	Json::Value PlainRtpTransport::GetStats() const
	{
		MS_TRACE();

		Json::Value json(Json::objectValue);

		return json;
	}

	void PlainRtpTransport::SetRemoteParameters(const std::string& ip, const uint16_t port)
	{
		int err;

		switch (Utils::IP::GetFamily(ip))
		{
			case AF_INET:
			{
				if (!Settings::configuration.hasIPv4)
					MS_THROW_ERROR("IPv4 disabled");

				err = uv_ip4_addr(
				  ip.c_str(),
				  static_cast<int>(port),
				  reinterpret_cast<struct sockaddr_in*>(&this->remoteAddrStorage));
				if (err != 0)
					MS_ABORT("uv_ipv4_addr() failed: %s", uv_strerror(err));

				break;
			}

			case AF_INET6:
			{
				if (!Settings::configuration.hasIPv6)
					MS_THROW_ERROR("IPv6 disabled");

				err = uv_ip6_addr(
				  ip.c_str(),
				  static_cast<int>(port),
				  reinterpret_cast<struct sockaddr_in6*>(&this->remoteAddrStorage));
				if (err != 0)
					MS_ABORT("uv_ipv6_addr() failed: %s", uv_strerror(err));

				break;
			}

			default:
			{
				MS_THROW_ERROR("invalid destination IP '%s'", ip.c_str());

				break;
			}
		}

		// Create a single tuple.
		this->tuple = new RTC::TransportTuple(
		  this->udpSocket, reinterpret_cast<struct sockaddr*>(&this->remoteAddrStorage));

		// Start the RTCP timer.
		this->rtcpTimer->Start(static_cast<uint64_t>(RTC::RTCP::MaxVideoIntervalMs / 2));
	}

	void PlainRtpTransport::SendRtpPacket(RTC::RtpPacket* packet)
	{
		MS_TRACE();

		if (!IsConnected())
			return;

		const uint8_t* data = packet->GetData();
		size_t len          = packet->GetSize();

		// Mirror RTP if needed.
		if (this->mirrorTuple != nullptr && this->mirroringOptions.sendRtp)
			this->mirrorTuple->Send(data, len);

		this->tuple->Send(data, len);
	}

	void PlainRtpTransport::SendRtcpPacket(RTC::RTCP::Packet* packet)
	{
		MS_TRACE();

		if (!IsConnected())
			return;

		const uint8_t* data = packet->GetData();
		size_t len          = packet->GetSize();

		// Mirror RTCP if needed.
		if (this->mirrorTuple != nullptr && this->mirroringOptions.sendRtcp)
			this->mirrorTuple->Send(data, len);

		this->tuple->Send(data, len);
	}

	void PlainRtpTransport::CreateSocket(int addressFamily, const std::string& localIP)
	{
		if (localIP.empty())
			this->udpSocket = new RTC::UdpSocket(this, addressFamily);
		else
			this->udpSocket = new RTC::UdpSocket(this, localIP);
	}

	bool PlainRtpTransport::IsConnected() const
	{
		return this->tuple ? true : false;
	}

	void PlainRtpTransport::SendRtcpCompoundPacket(RTC::RTCP::CompoundPacket* packet)
	{
		MS_TRACE();

		if (!IsConnected())
			return;

		const uint8_t* data = packet->GetData();
		size_t len          = packet->GetSize();

		// Mirror RTCP if needed.
		if (this->mirrorTuple != nullptr && this->mirroringOptions.sendRtcp)
			this->mirrorTuple->Send(data, len);

		this->tuple->Send(data, len);
	}

	inline void PlainRtpTransport::OnPacketRecv(RTC::TransportTuple* tuple, const uint8_t* data, size_t len)
	{
		MS_TRACE();

		// Check if it's RTCP.
		if (RTCP::Packet::IsRtcp(data, len))
		{
			OnRtcpDataRecv(tuple, data, len);
		}
		// Check if it's RTP.
		else if (RtpPacket::IsRtp(data, len))
		{
			OnRtpDataRecv(tuple, data, len);
		}
		else
		{
			MS_WARN_DEV("ignoring received packet of unknown type");
		}
	}

	inline void PlainRtpTransport::OnRtpDataRecv(
	  RTC::TransportTuple* /*tuple*/, const uint8_t* data, size_t len)
	{
		MS_TRACE();

		// Mirror RTP if needed.
		if (this->mirrorTuple != nullptr && this->mirroringOptions.recvRtp)
			this->mirrorTuple->Send(data, len);

		RTC::RtpPacket* packet = RTC::RtpPacket::Parse(data, len);

		if (packet == nullptr)
		{
			MS_WARN_TAG(rtp, "received data is not a valid RTP packet");

			return;
		}

		// Apply the Transport RTP header extension ids so the RTP listener can use them.

		if (this->headerExtensionIds.rid != 0u)
		{
			packet->AddExtensionMapping(
			  RtpHeaderExtensionUri::Type::RTP_STREAM_ID, this->headerExtensionIds.rid);
		}
		if (this->headerExtensionIds.absSendTime != 0u)
		{
			packet->AddExtensionMapping(
			  RtpHeaderExtensionUri::Type::ABS_SEND_TIME, this->headerExtensionIds.absSendTime);
		}

		// Get the associated Producer.
		RTC::Producer* producer = this->rtpListener.GetProducer(packet);

		if (producer == nullptr)
		{
			MS_WARN_TAG(
			  rtp,
			  "no suitable Producer for received RTP packet [ssrc:%" PRIu32 ", payloadType:%" PRIu8 "]",
			  packet->GetSsrc(),
			  packet->GetPayloadType());

			delete packet;
			return;
		}

		MS_DEBUG_DEV(
		  "RTP packet received [ssrc:%" PRIu32 ", payloadType:%" PRIu8 ", producer:%" PRIu32 "]",
		  packet->GetSsrc(),
		  packet->GetPayloadType(),
		  producer->producerId);

		// Pass the RTP packet to the corresponding Producer.
		producer->ReceiveRtpPacket(packet);

		delete packet;
	}

	inline void PlainRtpTransport::OnRtcpDataRecv(
	  RTC::TransportTuple* /*tuple*/, const uint8_t* data, size_t len)
	{
		MS_TRACE();

		// Mirror RTCP if needed.
		if (this->mirrorTuple != nullptr && this->mirroringOptions.recvRtcp)
			this->mirrorTuple->Send(data, len);

		RTC::RTCP::Packet* packet = RTC::RTCP::Packet::Parse(data, len);

		if (packet == nullptr)
		{
			MS_WARN_TAG(rtcp, "received data is not a valid RTCP compound or single packet");

			return;
		}

		// Handle each RTCP packet.
		while (packet != nullptr)
		{
			HandleRtcpPacket(packet);

			RTC::RTCP::Packet* previousPacket = packet;

			packet = packet->GetNext();
			delete previousPacket;
		}
	}

	void PlainRtpTransport::OnPacketRecv(
	  RTC::UdpSocket* socket, const uint8_t* data, size_t len, const struct sockaddr* remoteAddr)
	{
		MS_TRACE();

		RTC::TransportTuple tuple(socket, remoteAddr);

		OnPacketRecv(&tuple, data, len);
	}
} // namespace RTC
<|endoftext|>


<commit_before>
#include "FixturePropertySetting.h"

#include <easymodeling.h>

using namespace emodeling;

FixturePropertySetting::FixturePropertySetting(d2d::EditPanel* editPanel, libmodeling::Fixture* fixture)
	: d2d::IPropertySetting(editPanel, wxT("Body"))
	, m_fixture(fixture)
{
}

void FixturePropertySetting::updatePanel(d2d::PropertySettingPanel* panel)
{
	wxPropertyGrid* pg = panel->getPG();

	if (getPGType(pg) == m_type)
	{
		pg->GetProperty(wxT("Name"))->SetValue(m_fixture->name);
		pg->GetProperty(wxT("density"))->SetValue(m_fixture->density);
		pg->GetProperty(wxT("friction"))->SetValue(m_fixture->friction);
		pg->GetProperty(wxT("restitution"))->SetValue(m_fixture->restitution);
		pg->GetProperty(wxT("isSensor"))->SetValue(m_fixture->isSensor);
		pg->GetProperty(wxT("categoryBits"))->SetValue(m_fixture->categoryBits);
		pg->GetProperty(wxT("maskBits"))->SetValue(m_fixture->maskBits);
		pg->GetProperty(wxT("groupIndex"))->SetValue(m_fixture->groupIndex);
	}
	else
	{
		pg->Clear();

		pg->Append(new wxStringProperty(wxT("Type"), wxPG_LABEL, m_type));

		pg->Append(new wxStringProperty(wxT("Name"), wxPG_LABEL, m_fixture->name));

		pg->Append(new wxFloatProperty(wxT("density"), wxPG_LABEL, m_fixture->density));
		pg->SetPropertyAttribute(wxT("density"), "Precision", 2);

		pg->Append(new wxFloatProperty(wxT("friction"), wxPG_LABEL, m_fixture->friction));
		pg->SetPropertyAttribute(wxT("friction"), "Precision", 2);

		pg->Append(new wxFloatProperty(wxT("restitution"), wxPG_LABEL, m_fixture->restitution));
		pg->SetPropertyAttribute(wxT("restitution"), "Precision", 2);

		pg->Append(new wxBoolProperty(wxT("isSensor"), wxPG_LABEL, m_fixture->isSensor));

		pg->Append(new wxIntProperty(wxT("categoryBits"), wxPG_LABEL, m_fixture->categoryBits));
		pg->SetPropertyAttribute(wxT("categoryBits"), wxPG_ATTR_MIN, 0);
		pg->SetPropertyAttribute(wxT("categoryBits"), wxPG_ATTR_MAX, 0xFFFF);

		pg->Append(new wxIntProperty(wxT("maskBits"), wxPG_LABEL, m_fixture->maskBits));
		pg->SetPropertyAttribute(wxT("maskBits"), wxPG_ATTR_MIN, 0);
		pg->SetPropertyAttribute(wxT("maskBits"), wxPG_ATTR_MAX, 0xFFFF);

		pg->Append(new wxIntProperty(wxT("groupIndex"), wxPG_LABEL, m_fixture->groupIndex));
		pg->SetPropertyAttribute(wxT("groupIndex"), wxPG_ATTR_MIN, -32768);
		pg->SetPropertyAttribute(wxT("groupIndex"), wxPG_ATTR_MAX, 32767);
	}
}

void FixturePropertySetting::onPropertyGridChange(const wxString& name, const wxAny& value)
{
	if (value.IsNull())
		return;

	if (name == wxT("Name"))
		m_fixture->name = wxANY_AS(value, wxString);
	else if (name == wxT("density"))
		m_fixture->density = wxANY_AS(value, float);
	else if (name == wxT("friction"))
		m_fixture->friction = wxANY_AS(value, float);
	else if (name == wxT("restitution"))
		m_fixture->restitution = wxANY_AS(value, float);
	else if (name == wxT("isSensor"))
		m_fixture->isSensor = wxANY_AS(value, bool);
	else if (name == wxT("categoryBits"))
		m_fixture->categoryBits = wxANY_AS(value, int);
	else if (name == wxT("maskBits"))
		m_fixture->maskBits = wxANY_AS(value, int);
	else if (name == wxT("groupIndex"))
		m_fixture->groupIndex = wxANY_AS(value, int);

	m_editPanel->Refresh();
}

void FixturePropertySetting::updatePropertyGrid(d2d::PropertySettingPanel* panel)
{
	updatePanel(panel);
}

void FixturePropertySetting::enablePropertyGrid(d2d::PropertySettingPanel* panel, bool bEnable)
{
	//
}
<commit_msg>[FIXED] emodel property<commit_after>
#include "FixturePropertySetting.h"

#include <easymodeling.h>

using namespace emodeling;

FixturePropertySetting::FixturePropertySetting(d2d::EditPanel* editPanel, libmodeling::Fixture* fixture)
	: d2d::IPropertySetting(editPanel, wxT("Fixture"))
	, m_fixture(fixture)
{
}

void FixturePropertySetting::updatePanel(d2d::PropertySettingPanel* panel)
{
	wxPropertyGrid* pg = panel->getPG();

	if (getPGType(pg) == m_type)
	{
		pg->GetProperty(wxT("Name"))->SetValue(m_fixture->name);
		pg->GetProperty(wxT("density"))->SetValue(m_fixture->density);
		pg->GetProperty(wxT("friction"))->SetValue(m_fixture->friction);
		pg->GetProperty(wxT("restitution"))->SetValue(m_fixture->restitution);
		pg->GetProperty(wxT("isSensor"))->SetValue(m_fixture->isSensor);
		pg->GetProperty(wxT("categoryBits"))->SetValue(m_fixture->categoryBits);
		pg->GetProperty(wxT("maskBits"))->SetValue(m_fixture->maskBits);
		pg->GetProperty(wxT("groupIndex"))->SetValue(m_fixture->groupIndex);
	}
	else
	{
		pg->Clear();

		pg->Append(new wxStringProperty(wxT("Type"), wxPG_LABEL, m_type));

		pg->Append(new wxStringProperty(wxT("Name"), wxPG_LABEL, m_fixture->name));

		pg->Append(new wxFloatProperty(wxT("density"), wxPG_LABEL, m_fixture->density));
		pg->SetPropertyAttribute(wxT("density"), "Precision", 2);

		pg->Append(new wxFloatProperty(wxT("friction"), wxPG_LABEL, m_fixture->friction));
		pg->SetPropertyAttribute(wxT("friction"), "Precision", 2);

		pg->Append(new wxFloatProperty(wxT("restitution"), wxPG_LABEL, m_fixture->restitution));
		pg->SetPropertyAttribute(wxT("restitution"), "Precision", 2);

		pg->Append(new wxBoolProperty(wxT("isSensor"), wxPG_LABEL, m_fixture->isSensor));

		pg->Append(new wxIntProperty(wxT("categoryBits"), wxPG_LABEL, m_fixture->categoryBits));
		pg->SetPropertyAttribute(wxT("categoryBits"), wxPG_ATTR_MIN, 0);
		pg->SetPropertyAttribute(wxT("categoryBits"), wxPG_ATTR_MAX, 0xFFFF);

		pg->Append(new wxIntProperty(wxT("maskBits"), wxPG_LABEL, m_fixture->maskBits));
		pg->SetPropertyAttribute(wxT("maskBits"), wxPG_ATTR_MIN, 0);
		pg->SetPropertyAttribute(wxT("maskBits"), wxPG_ATTR_MAX, 0xFFFF);

		pg->Append(new wxIntProperty(wxT("groupIndex"), wxPG_LABEL, m_fixture->groupIndex));
		pg->SetPropertyAttribute(wxT("groupIndex"), wxPG_ATTR_MIN, -32768);
		pg->SetPropertyAttribute(wxT("groupIndex"), wxPG_ATTR_MAX, 32767);
	}
}

void FixturePropertySetting::onPropertyGridChange(const wxString& name, const wxAny& value)
{
	if (value.IsNull())
		return;

	if (name == wxT("Name"))
		m_fixture->name = wxANY_AS(value, wxString);
	else if (name == wxT("density"))
		m_fixture->density = wxANY_AS(value, float);
	else if (name == wxT("friction"))
		m_fixture->friction = wxANY_AS(value, float);
	else if (name == wxT("restitution"))
		m_fixture->restitution = wxANY_AS(value, float);
	else if (name == wxT("isSensor"))
		m_fixture->isSensor = wxANY_AS(value, bool);
	else if (name == wxT("categoryBits"))
		m_fixture->categoryBits = wxANY_AS(value, int);
	else if (name == wxT("maskBits"))
		m_fixture->maskBits = wxANY_AS(value, int);
	else if (name == wxT("groupIndex"))
		m_fixture->groupIndex = wxANY_AS(value, int);

	m_editPanel->Refresh();
}

void FixturePropertySetting::updatePropertyGrid(d2d::PropertySettingPanel* panel)
{
	updatePanel(panel);
}

void FixturePropertySetting::enablePropertyGrid(d2d::PropertySettingPanel* panel, bool bEnable)
{
	//
}
<|endoftext|>


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

#include "include/core/SkSurface.h"
#include "include/gpu/GrBackendSurface.h"
#include "include/gpu/GrDirectContext.h"
#include "src/core/SkAutoMalloc.h"
#include "tools/sk_app/DawnWindowContext.h"

#include "dawn/dawn_proc.h"

static wgpu::TextureUsage kUsage = wgpu::TextureUsage::OutputAttachment |
                                   wgpu::TextureUsage::CopySrc;

static void PrintDeviceError(WGPUErrorType, const char* message, void*) {
    printf("Device error: %s\n", message);
    SkASSERT(false);
}

namespace sk_app {

DawnWindowContext::DawnWindowContext(const DisplayParams& params,
                                     wgpu::TextureFormat swapChainFormat)
    : WindowContext(params)
    , fSwapChainFormat(swapChainFormat)
    , fInstance(std::make_unique<dawn_native::Instance>()) {
}

void DawnWindowContext::initializeContext(int width, int height) {
    SkASSERT(!fContext);

    fWidth = width;
    fHeight = height;
    fDevice = onInitializeContext();

    fContext = GrDirectContext::MakeDawn(fDevice, fDisplayParams.fGrContextOptions);
    if (!fContext) {
        return;
    }
    fSwapChainImplementation = this->createSwapChainImplementation(-1, -1, fDisplayParams);
    wgpu::SwapChainDescriptor swapChainDesc;
    swapChainDesc.implementation = reinterpret_cast<int64_t>(&fSwapChainImplementation);
    fSwapChain = fDevice.CreateSwapChain(nullptr, &swapChainDesc);
    if (!fSwapChain) {
        fContext.reset();
        return;
    }
    fSwapChain.Configure(fSwapChainFormat, kUsage, width, height);
    fDevice.SetUncapturedErrorCallback(PrintDeviceError, 0);
}

DawnWindowContext::~DawnWindowContext() {
}

void DawnWindowContext::destroyContext() {
    if (!fDevice.Get()) {
        return;
    }

    this->onDestroyContext();

    fContext.reset();
    fDevice = nullptr;
}

sk_sp<SkSurface> DawnWindowContext::getBackbufferSurface() {
    GrDawnRenderTargetInfo rtInfo;
    rtInfo.fTextureView = fSwapChain.GetCurrentTextureView();
    rtInfo.fFormat = fSwapChainFormat;
    rtInfo.fLevelCount = 1; // FIXME
    GrBackendRenderTarget backendRenderTarget(fWidth, fHeight, fDisplayParams.fMSAASampleCount, 8,
                                              rtInfo);
    fSurface = SkSurface::MakeFromBackendRenderTarget(fContext.get(),
                                                      backendRenderTarget,
                                                      this->getRTOrigin(),
                                                      fDisplayParams.fColorType,
                                                      fDisplayParams.fColorSpace,
                                                      &fDisplayParams.fSurfaceProps);
    return fSurface;
}

void DawnWindowContext::swapBuffers() {
    fSwapChain.Present();
    this->onSwapBuffers();
}

void DawnWindowContext::resize(int w, int h) {
    fWidth = w;
    fHeight = h;
    fSwapChainImplementation = this->createSwapChainImplementation(w, h, fDisplayParams);
    wgpu::SwapChainDescriptor swapChainDesc;
    swapChainDesc.implementation = reinterpret_cast<int64_t>(&fSwapChainImplementation);
    fSwapChain = fDevice.CreateSwapChain(nullptr, &swapChainDesc);
    if (!fSwapChain) {
        fContext.reset();
        return;
    }
    fSwapChain.Configure(fSwapChainFormat, kUsage, fWidth, fHeight);
}

void DawnWindowContext::setDisplayParams(const DisplayParams& params) {
    fDisplayParams = params;
}

wgpu::Device DawnWindowContext::createDevice(dawn_native::BackendType type) {
    fInstance->DiscoverDefaultAdapters();
    DawnProcTable backendProcs = dawn_native::GetProcs();
    dawnProcSetProcs(&backendProcs);

    std::vector<dawn_native::Adapter> adapters = fInstance->GetAdapters();
    for (dawn_native::Adapter adapter : adapters) {
        if (adapter.GetBackendType() == type) {
            return adapter.CreateDevice();
        }
    }
    return nullptr;
}

}   //namespace sk_app
<commit_msg>Fix usage of deprecated wgpu::TextureUsage::OutputAttachment<commit_after>/*
 * Copyright 2019 Google Inc.
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#include "include/core/SkSurface.h"
#include "include/gpu/GrBackendSurface.h"
#include "include/gpu/GrDirectContext.h"
#include "src/core/SkAutoMalloc.h"
#include "tools/sk_app/DawnWindowContext.h"

#include "dawn/dawn_proc.h"

static wgpu::TextureUsage kUsage = wgpu::TextureUsage::RenderAttachment |
                                   wgpu::TextureUsage::CopySrc;

static void PrintDeviceError(WGPUErrorType, const char* message, void*) {
    printf("Device error: %s\n", message);
    SkASSERT(false);
}

namespace sk_app {

DawnWindowContext::DawnWindowContext(const DisplayParams& params,
                                     wgpu::TextureFormat swapChainFormat)
    : WindowContext(params)
    , fSwapChainFormat(swapChainFormat)
    , fInstance(std::make_unique<dawn_native::Instance>()) {
}

void DawnWindowContext::initializeContext(int width, int height) {
    SkASSERT(!fContext);

    fWidth = width;
    fHeight = height;
    fDevice = onInitializeContext();

    fContext = GrDirectContext::MakeDawn(fDevice, fDisplayParams.fGrContextOptions);
    if (!fContext) {
        return;
    }
    fSwapChainImplementation = this->createSwapChainImplementation(-1, -1, fDisplayParams);
    wgpu::SwapChainDescriptor swapChainDesc;
    swapChainDesc.implementation = reinterpret_cast<int64_t>(&fSwapChainImplementation);
    fSwapChain = fDevice.CreateSwapChain(nullptr, &swapChainDesc);
    if (!fSwapChain) {
        fContext.reset();
        return;
    }
    fSwapChain.Configure(fSwapChainFormat, kUsage, width, height);
    fDevice.SetUncapturedErrorCallback(PrintDeviceError, 0);
}

DawnWindowContext::~DawnWindowContext() {
}

void DawnWindowContext::destroyContext() {
    if (!fDevice.Get()) {
        return;
    }

    this->onDestroyContext();

    fContext.reset();
    fDevice = nullptr;
}

sk_sp<SkSurface> DawnWindowContext::getBackbufferSurface() {
    GrDawnRenderTargetInfo rtInfo;
    rtInfo.fTextureView = fSwapChain.GetCurrentTextureView();
    rtInfo.fFormat = fSwapChainFormat;
    rtInfo.fLevelCount = 1; // FIXME
    GrBackendRenderTarget backendRenderTarget(fWidth, fHeight, fDisplayParams.fMSAASampleCount, 8,
                                              rtInfo);
    fSurface = SkSurface::MakeFromBackendRenderTarget(fContext.get(),
                                                      backendRenderTarget,
                                                      this->getRTOrigin(),
                                                      fDisplayParams.fColorType,
                                                      fDisplayParams.fColorSpace,
                                                      &fDisplayParams.fSurfaceProps);
    return fSurface;
}

void DawnWindowContext::swapBuffers() {
    fSwapChain.Present();
    this->onSwapBuffers();
}

void DawnWindowContext::resize(int w, int h) {
    fWidth = w;
    fHeight = h;
    fSwapChainImplementation = this->createSwapChainImplementation(w, h, fDisplayParams);
    wgpu::SwapChainDescriptor swapChainDesc;
    swapChainDesc.implementation = reinterpret_cast<int64_t>(&fSwapChainImplementation);
    fSwapChain = fDevice.CreateSwapChain(nullptr, &swapChainDesc);
    if (!fSwapChain) {
        fContext.reset();
        return;
    }
    fSwapChain.Configure(fSwapChainFormat, kUsage, fWidth, fHeight);
}

void DawnWindowContext::setDisplayParams(const DisplayParams& params) {
    fDisplayParams = params;
}

wgpu::Device DawnWindowContext::createDevice(dawn_native::BackendType type) {
    fInstance->DiscoverDefaultAdapters();
    DawnProcTable backendProcs = dawn_native::GetProcs();
    dawnProcSetProcs(&backendProcs);

    std::vector<dawn_native::Adapter> adapters = fInstance->GetAdapters();
    for (dawn_native::Adapter adapter : adapters) {
        if (adapter.GetBackendType() == type) {
            return adapter.CreateDevice();
        }
    }
    return nullptr;
}

}   //namespace sk_app
<|endoftext|>


<commit_before>// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/browser/chromeos/drive/drive_download_handler.h"

#include "base/bind.h"
#include "base/file_util.h"
#include "base/supports_user_data.h"
#include "chrome/browser/chromeos/drive/drive.pb.h"
#include "chrome/browser/chromeos/drive/drive_file_system_interface.h"
#include "chrome/browser/chromeos/drive/drive_file_system_util.h"
#include "chrome/browser/chromeos/drive/drive_system_service.h"
#include "chrome/browser/chromeos/drive/file_write_helper.h"
#include "content/public/browser/browser_thread.h"

using content::BrowserThread;
using content::DownloadManager;
using content::DownloadItem;

namespace drive {
namespace {

// Key for base::SupportsUserData::Data.
const char kDrivePathKey[] = "DrivePath";

// User Data stored in DownloadItem for drive path.
class DriveUserData : public base::SupportsUserData::Data {
 public:
  explicit DriveUserData(const FilePath& path) : file_path_(path) {}
  virtual ~DriveUserData() {}

  const FilePath& file_path() const { return file_path_; }

 private:
  const FilePath file_path_;
};

// Extracts DriveUserData* from |download|.
const DriveUserData* GetDriveUserData(const DownloadItem* download) {
  return static_cast<const DriveUserData*>(
      download->GetUserData(&kDrivePathKey));
}

// Creates a temporary file |drive_tmp_download_path| in
// |drive_tmp_download_dir|. Must be called on a thread that allows file
// operations.
FilePath GetDriveTempDownloadPath(const FilePath& drive_tmp_download_dir) {
  bool created = file_util::CreateDirectory(drive_tmp_download_dir);
  DCHECK(created) << "Can not create temp download directory at "
                  << drive_tmp_download_dir.value();
  FilePath drive_tmp_download_path;
  created = file_util::CreateTemporaryFileInDir(drive_tmp_download_dir,
                                                &drive_tmp_download_path);
  DCHECK(created) << "Temporary download file creation failed";
  return drive_tmp_download_path;
}

// Moves downloaded file to Drive.
void MoveDownloadedFile(const FilePath& downloaded_file,
                        DriveFileError error,
                        const FilePath& dest_path) {
  if (error != DRIVE_FILE_OK)
    return;
  file_util::Move(downloaded_file, dest_path);
}

}  // namespace

DriveDownloadHandler::DriveDownloadHandler(
    FileWriteHelper* file_write_helper,
    DriveFileSystemInterface* file_system)
    : file_write_helper_(file_write_helper),
      file_system_(file_system),
      ALLOW_THIS_IN_INITIALIZER_LIST(weak_ptr_factory_(this)) {
}

DriveDownloadHandler::~DriveDownloadHandler() {
}

// static
DriveDownloadHandler* DriveDownloadHandler::GetForProfile(Profile* profile) {
  DriveSystemService* system_service =
      DriveSystemServiceFactory::GetForProfile(profile);
  return system_service ? system_service->download_handler() : NULL;
}

void DriveDownloadHandler::Initialize(
    DownloadManager* download_manager,
    const FilePath& drive_tmp_download_path) {
  DCHECK(!drive_tmp_download_path.empty());
  if (download_manager)
    notifier_.reset(new AllDownloadItemNotifier(download_manager, this));
  drive_tmp_download_path_ = drive_tmp_download_path;
}

void DriveDownloadHandler::SubstituteDriveDownloadPath(
    const FilePath& drive_path,
    content::DownloadItem* download,
    const SubstituteDriveDownloadPathCallback& callback) {
  DVLOG(1) << "SubstituteDriveDownloadPath " << drive_path.value();

  SetDownloadParams(drive_path, download);

  if (util::IsUnderDriveMountPoint(drive_path)) {
    // Can't access drive if the directory does not exist on Drive.
    // We set off a chain of callbacks as follows:
    // DriveFileSystem::GetEntryInfoByPath
    //   OnEntryFound calls DriveFileSystem::CreateDirectory (if necessary)
    //     OnCreateDirectory calls SubstituteDriveDownloadPathInternal
    const FilePath drive_dir_path =
        util::ExtractDrivePath(drive_path.DirName());
    // Ensure the directory exists. This also forces DriveFileSystem to
    // initialize DriveRootDirectory.
    file_system_->GetEntryInfoByPath(
        drive_dir_path,
        base::Bind(&DriveDownloadHandler::OnEntryFound,
                   weak_ptr_factory_.GetWeakPtr(),
                   drive_dir_path,
                   callback));
  } else {
    callback.Run(drive_path);
  }
}

void DriveDownloadHandler::SetDownloadParams(const FilePath& drive_path,
                                             DownloadItem* download) {
  if (!download || (download->GetState() != DownloadItem::IN_PROGRESS))
    return;

  if (util::IsUnderDriveMountPoint(drive_path)) {
    download->SetUserData(&kDrivePathKey, new DriveUserData(drive_path));
    download->SetDisplayName(drive_path.BaseName());
    download->SetIsTemporary(true);
  } else if (IsDriveDownload(download)) {
    // This may have been previously set if the default download folder is
    // /drive, and the user has now changed the download target to a local
    // folder.
    download->SetUserData(&kDrivePathKey, NULL);
    download->SetDisplayName(drive_path);
    // TODO(achuith): This is not quite right.
    download->SetIsTemporary(false);
  }
}

FilePath DriveDownloadHandler::GetTargetPath(const DownloadItem* download) {
  const DriveUserData* data = GetDriveUserData(download);
  // If data is NULL, we've somehow lost the drive path selected by the file
  // picker.
  DCHECK(data);
  return data ? data->file_path() : FilePath();
}

bool DriveDownloadHandler::IsDriveDownload(const DownloadItem* download) {
  // We use the existence of the DriveUserData object in download as a
  // signal that this is a DriveDownload.
  return GetDriveUserData(download) != NULL;
}

void DriveDownloadHandler::OnDownloadUpdated(
    DownloadManager* manager, DownloadItem* download) {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));

  // Drive downloads are considered temporary downloads. Only accept downloads
  // that have the Drive meta data associated with them. Otherwise we might trip
  // over non-Drive downloads being saved to drive_tmp_download_path_.
  if (!download->IsTemporary() ||
      (download->GetTargetFilePath().DirName() != drive_tmp_download_path_) ||
      !IsDriveDownload(download))
    return;

  switch (download->GetState()) {
    case DownloadItem::IN_PROGRESS:
      break;

    case DownloadItem::COMPLETE:
      UploadDownloadItem(download);
      // Reset user data here to filter out subsequent updates from this item.
      download->SetUserData(&kDrivePathKey, NULL);
      break;

    case DownloadItem::CANCELLED:
    case DownloadItem::INTERRUPTED:
      download->SetUserData(&kDrivePathKey, NULL);
      break;

    default:
      NOTREACHED();
  }
}

void DriveDownloadHandler::OnEntryFound(
    const FilePath& drive_dir_path,
    const SubstituteDriveDownloadPathCallback& callback,
    DriveFileError error,
    scoped_ptr<DriveEntryProto> entry_proto) {
  if (error == DRIVE_FILE_ERROR_NOT_FOUND) {
    // Destination Drive directory doesn't exist, so create it.
    const bool is_exclusive = false, is_recursive = true;
    file_system_->CreateDirectory(
        drive_dir_path, is_exclusive, is_recursive,
        base::Bind(&DriveDownloadHandler::OnCreateDirectory,
                   weak_ptr_factory_.GetWeakPtr(),
                   callback));
  } else if (error == DRIVE_FILE_OK) {
    // Directory is already ready.
    OnCreateDirectory(callback, DRIVE_FILE_OK);
  } else {
    LOG(WARNING) << "Failed to get entry info for path: "
                 << drive_dir_path.value() << ", error = " << error;
    callback.Run(FilePath());
  }
}

void DriveDownloadHandler::OnCreateDirectory(
    const SubstituteDriveDownloadPathCallback& callback,
    DriveFileError error) {
  DVLOG(1) << "OnCreateDirectory " << error;
  if (error == DRIVE_FILE_OK) {
    base::PostTaskAndReplyWithResult(
        BrowserThread::GetBlockingPool(),
        FROM_HERE,
        base::Bind(&GetDriveTempDownloadPath, drive_tmp_download_path_),
        callback);
  } else {
    LOG(WARNING) << "Failed to create directory, error = " << error;
    callback.Run(FilePath());
  }
}

void DriveDownloadHandler::UploadDownloadItem(DownloadItem* download) {
  DCHECK(download->IsComplete());
  file_write_helper_->PrepareWritableFileAndRun(
      util::ExtractDrivePath(GetTargetPath(download)),
      base::Bind(&MoveDownloadedFile, download->GetTargetFilePath()));
}

}  // namespace drive
<commit_msg>chromeos: Stop creating DriveSystemService from ChromeDownloadManagerDelegate in tests<commit_after>// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/browser/chromeos/drive/drive_download_handler.h"

#include "base/bind.h"
#include "base/file_util.h"
#include "base/supports_user_data.h"
#include "chrome/browser/chromeos/drive/drive.pb.h"
#include "chrome/browser/chromeos/drive/drive_file_system_interface.h"
#include "chrome/browser/chromeos/drive/drive_file_system_util.h"
#include "chrome/browser/chromeos/drive/drive_system_service.h"
#include "chrome/browser/chromeos/drive/file_write_helper.h"
#include "content/public/browser/browser_thread.h"

using content::BrowserThread;
using content::DownloadManager;
using content::DownloadItem;

namespace drive {
namespace {

// Key for base::SupportsUserData::Data.
const char kDrivePathKey[] = "DrivePath";

// User Data stored in DownloadItem for drive path.
class DriveUserData : public base::SupportsUserData::Data {
 public:
  explicit DriveUserData(const FilePath& path) : file_path_(path) {}
  virtual ~DriveUserData() {}

  const FilePath& file_path() const { return file_path_; }

 private:
  const FilePath file_path_;
};

// Extracts DriveUserData* from |download|.
const DriveUserData* GetDriveUserData(const DownloadItem* download) {
  return static_cast<const DriveUserData*>(
      download->GetUserData(&kDrivePathKey));
}

// Creates a temporary file |drive_tmp_download_path| in
// |drive_tmp_download_dir|. Must be called on a thread that allows file
// operations.
FilePath GetDriveTempDownloadPath(const FilePath& drive_tmp_download_dir) {
  bool created = file_util::CreateDirectory(drive_tmp_download_dir);
  DCHECK(created) << "Can not create temp download directory at "
                  << drive_tmp_download_dir.value();
  FilePath drive_tmp_download_path;
  created = file_util::CreateTemporaryFileInDir(drive_tmp_download_dir,
                                                &drive_tmp_download_path);
  DCHECK(created) << "Temporary download file creation failed";
  return drive_tmp_download_path;
}

// Moves downloaded file to Drive.
void MoveDownloadedFile(const FilePath& downloaded_file,
                        DriveFileError error,
                        const FilePath& dest_path) {
  if (error != DRIVE_FILE_OK)
    return;
  file_util::Move(downloaded_file, dest_path);
}

}  // namespace

DriveDownloadHandler::DriveDownloadHandler(
    FileWriteHelper* file_write_helper,
    DriveFileSystemInterface* file_system)
    : file_write_helper_(file_write_helper),
      file_system_(file_system),
      ALLOW_THIS_IN_INITIALIZER_LIST(weak_ptr_factory_(this)) {
}

DriveDownloadHandler::~DriveDownloadHandler() {
}

// static
DriveDownloadHandler* DriveDownloadHandler::GetForProfile(Profile* profile) {
  DriveSystemService* system_service =
      DriveSystemServiceFactory::FindForProfile(profile);
  return system_service ? system_service->download_handler() : NULL;
}

void DriveDownloadHandler::Initialize(
    DownloadManager* download_manager,
    const FilePath& drive_tmp_download_path) {
  DCHECK(!drive_tmp_download_path.empty());
  if (download_manager)
    notifier_.reset(new AllDownloadItemNotifier(download_manager, this));
  drive_tmp_download_path_ = drive_tmp_download_path;
}

void DriveDownloadHandler::SubstituteDriveDownloadPath(
    const FilePath& drive_path,
    content::DownloadItem* download,
    const SubstituteDriveDownloadPathCallback& callback) {
  DVLOG(1) << "SubstituteDriveDownloadPath " << drive_path.value();

  SetDownloadParams(drive_path, download);

  if (util::IsUnderDriveMountPoint(drive_path)) {
    // Can't access drive if the directory does not exist on Drive.
    // We set off a chain of callbacks as follows:
    // DriveFileSystem::GetEntryInfoByPath
    //   OnEntryFound calls DriveFileSystem::CreateDirectory (if necessary)
    //     OnCreateDirectory calls SubstituteDriveDownloadPathInternal
    const FilePath drive_dir_path =
        util::ExtractDrivePath(drive_path.DirName());
    // Ensure the directory exists. This also forces DriveFileSystem to
    // initialize DriveRootDirectory.
    file_system_->GetEntryInfoByPath(
        drive_dir_path,
        base::Bind(&DriveDownloadHandler::OnEntryFound,
                   weak_ptr_factory_.GetWeakPtr(),
                   drive_dir_path,
                   callback));
  } else {
    callback.Run(drive_path);
  }
}

void DriveDownloadHandler::SetDownloadParams(const FilePath& drive_path,
                                             DownloadItem* download) {
  if (!download || (download->GetState() != DownloadItem::IN_PROGRESS))
    return;

  if (util::IsUnderDriveMountPoint(drive_path)) {
    download->SetUserData(&kDrivePathKey, new DriveUserData(drive_path));
    download->SetDisplayName(drive_path.BaseName());
    download->SetIsTemporary(true);
  } else if (IsDriveDownload(download)) {
    // This may have been previously set if the default download folder is
    // /drive, and the user has now changed the download target to a local
    // folder.
    download->SetUserData(&kDrivePathKey, NULL);
    download->SetDisplayName(drive_path);
    // TODO(achuith): This is not quite right.
    download->SetIsTemporary(false);
  }
}

FilePath DriveDownloadHandler::GetTargetPath(const DownloadItem* download) {
  const DriveUserData* data = GetDriveUserData(download);
  // If data is NULL, we've somehow lost the drive path selected by the file
  // picker.
  DCHECK(data);
  return data ? data->file_path() : FilePath();
}

bool DriveDownloadHandler::IsDriveDownload(const DownloadItem* download) {
  // We use the existence of the DriveUserData object in download as a
  // signal that this is a DriveDownload.
  return GetDriveUserData(download) != NULL;
}

void DriveDownloadHandler::OnDownloadUpdated(
    DownloadManager* manager, DownloadItem* download) {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));

  // Drive downloads are considered temporary downloads. Only accept downloads
  // that have the Drive meta data associated with them. Otherwise we might trip
  // over non-Drive downloads being saved to drive_tmp_download_path_.
  if (!download->IsTemporary() ||
      (download->GetTargetFilePath().DirName() != drive_tmp_download_path_) ||
      !IsDriveDownload(download))
    return;

  switch (download->GetState()) {
    case DownloadItem::IN_PROGRESS:
      break;

    case DownloadItem::COMPLETE:
      UploadDownloadItem(download);
      // Reset user data here to filter out subsequent updates from this item.
      download->SetUserData(&kDrivePathKey, NULL);
      break;

    case DownloadItem::CANCELLED:
    case DownloadItem::INTERRUPTED:
      download->SetUserData(&kDrivePathKey, NULL);
      break;

    default:
      NOTREACHED();
  }
}

void DriveDownloadHandler::OnEntryFound(
    const FilePath& drive_dir_path,
    const SubstituteDriveDownloadPathCallback& callback,
    DriveFileError error,
    scoped_ptr<DriveEntryProto> entry_proto) {
  if (error == DRIVE_FILE_ERROR_NOT_FOUND) {
    // Destination Drive directory doesn't exist, so create it.
    const bool is_exclusive = false, is_recursive = true;
    file_system_->CreateDirectory(
        drive_dir_path, is_exclusive, is_recursive,
        base::Bind(&DriveDownloadHandler::OnCreateDirectory,
                   weak_ptr_factory_.GetWeakPtr(),
                   callback));
  } else if (error == DRIVE_FILE_OK) {
    // Directory is already ready.
    OnCreateDirectory(callback, DRIVE_FILE_OK);
  } else {
    LOG(WARNING) << "Failed to get entry info for path: "
                 << drive_dir_path.value() << ", error = " << error;
    callback.Run(FilePath());
  }
}

void DriveDownloadHandler::OnCreateDirectory(
    const SubstituteDriveDownloadPathCallback& callback,
    DriveFileError error) {
  DVLOG(1) << "OnCreateDirectory " << error;
  if (error == DRIVE_FILE_OK) {
    base::PostTaskAndReplyWithResult(
        BrowserThread::GetBlockingPool(),
        FROM_HERE,
        base::Bind(&GetDriveTempDownloadPath, drive_tmp_download_path_),
        callback);
  } else {
    LOG(WARNING) << "Failed to create directory, error = " << error;
    callback.Run(FilePath());
  }
}

void DriveDownloadHandler::UploadDownloadItem(DownloadItem* download) {
  DCHECK(download->IsComplete());
  file_write_helper_->PrepareWritableFileAndRun(
      util::ExtractDrivePath(GetTargetPath(download)),
      base::Bind(&MoveDownloadedFile, download->GetTargetFilePath()));
}

}  // namespace drive
<|endoftext|>