<commit_before>/*
 * Copyright (C) 2004, 2006 Apple Computer, Inc.  All rights reserved.
 * Copyright (C) 2007-2009 Google, Inc.  All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * 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 "NPV8Object.h"
#include "npruntime_priv.h"
#include "V8NPObject.h"

#include <wtf/HashMap.h>
#include <wtf/HashSet.h>
#include <wtf/Assertions.h>

// FIXME: Consider removing locks if we're singlethreaded already.
// The static initializer here should work okay, but we want to avoid
// static initialization in general.
//
// Commenting out the locks to avoid dependencies on chrome for now.
// Need a platform abstraction which we can use.
// static Lock StringIdentifierMapLock;

namespace {

// We use StringKey here as the key-type to avoid a string copy to
// construct the map key and for faster comparisons than strcmp.
class StringKey {
  public:
    explicit StringKey(const char* str) : _string(str), _length(strlen(str)) {}
    StringKey() : _string(0), _length(0) {}
    explicit StringKey(WTF::HashTableDeletedValueType)
        : _string(hashTableDeletedValue()), _length(0) { }

    StringKey& operator=(const StringKey& other) {
        this->_string = other._string;
        this->_length = other._length;
        return *this;
    }

    bool isHashTableDeletedValue() const {
        return _string == hashTableDeletedValue();
    }

    const char* _string;
    size_t _length;
  private:
    const char* hashTableDeletedValue() const {
        return reinterpret_cast<const char*>(-1);
    }
};

inline bool operator==(const StringKey& x, const StringKey& y) {
    if (x._length != y._length) {
        return false;
    } else if (x._string == y._string) {
        return true;
    } else {
        ASSERT(!x.isHashTableDeletedValue() && !y.isHashTableDeletedValue());
        return memcmp(x._string, y._string, y._length) == 0;
    }
}

// Implement WTF::DefaultHash<StringKey>::Hash interface.
struct StringKeyHash {
    static unsigned hash(const StringKey& key) {
        // Use the same string hash function as in V8.
        unsigned hash = 0;
        size_t len = key._length;
        const char* str = key._string;
        for (size_t i = 0; i < len; i++) {
            char c = str[i];
            hash += c;
            hash += (hash << 10);
            hash ^= (hash >> 6);
        }
        hash += (hash << 3);
        hash ^= (hash >> 11);
        hash += (hash << 15);
        if (hash == 0) {
            hash = 27;
        }
        return hash;
    }

    static bool equal(const StringKey& x, const StringKey& y) {
        return x == y;
    }

    static const bool safeToCompareToEmptyOrDeleted = true;
};

}  // namespace

// Implement HashTraits<StringKey>
struct StringKeyHashTraits : WTF::GenericHashTraits<StringKey> {
    static void constructDeletedValue(StringKey& slot) {
        new (&slot) StringKey(WTF::HashTableDeletedValue);
    }
    static bool isDeletedValue(const StringKey& value) {
        return value.isHashTableDeletedValue();
    }
};

typedef WTF::HashMap<StringKey, PrivateIdentifier*, \
        StringKeyHash, StringKeyHashTraits> StringIdentifierMap;

static StringIdentifierMap* getStringIdentifierMap() {
    static StringIdentifierMap* stringIdentifierMap = 0;
    if (!stringIdentifierMap)
        stringIdentifierMap = new StringIdentifierMap();
    return stringIdentifierMap;
}

// FIXME: Consider removing locks if we're singlethreaded already.
// static Lock IntIdentifierMapLock;

typedef WTF::HashMap<int, PrivateIdentifier*> IntIdentifierMap;

static IntIdentifierMap* getIntIdentifierMap() {
    static IntIdentifierMap* intIdentifierMap = 0;
    if (!intIdentifierMap)
        intIdentifierMap = new IntIdentifierMap();
    return intIdentifierMap;
}

extern "C" {

NPIdentifier NPN_GetStringIdentifier(const NPUTF8* name) {
    ASSERT(name);

    if (name) {
        // AutoLock safeLock(StringIdentifierMapLock);

        StringKey key(name);
        StringIdentifierMap* identMap = getStringIdentifierMap();
        StringIdentifierMap::iterator iter = identMap->find(key);
        if (iter != identMap->end())
            return static_cast<NPIdentifier>(iter->second);

        size_t nameLen = key._length;

        // We never release identifiers, so this dictionary will grow.
        PrivateIdentifier* identifier = static_cast<PrivateIdentifier*>(
            malloc(sizeof(PrivateIdentifier) + nameLen + 1));
        char* nameStorage = reinterpret_cast<char*>(identifier + 1);
        memcpy(nameStorage, name, nameLen + 1);
        identifier->isString = true;
        identifier->value.string = reinterpret_cast<NPUTF8*>(nameStorage);
        key._string = nameStorage;
        identMap->set(key, identifier);
        return (NPIdentifier)identifier;
    }

    return 0;
}

void NPN_GetStringIdentifiers(const NPUTF8** names, int32_t nameCount,
                              NPIdentifier* identifiers) {
    ASSERT(names);
    ASSERT(identifiers);

    if (names && identifiers)
        for (int i = 0; i < nameCount; i++)
            identifiers[i] = NPN_GetStringIdentifier(names[i]);
}

NPIdentifier NPN_GetIntIdentifier(int32_t intid) {
    // AutoLock safeLock(IntIdentifierMapLock);

    IntIdentifierMap* identMap = getIntIdentifierMap();
    IntIdentifierMap::iterator iter = identMap->find(intid);
    if (iter != identMap->end())
        return static_cast<NPIdentifier>(iter->second);

    // We never release identifiers, so this dictionary will grow.
    PrivateIdentifier* identifier = reinterpret_cast<PrivateIdentifier*>(
        malloc(sizeof(PrivateIdentifier)));
    identifier->isString = false;
    identifier->value.number = intid;
    identMap->set(intid, identifier);
    return (NPIdentifier)identifier;
}

bool NPN_IdentifierIsString(NPIdentifier identifier) {
    PrivateIdentifier* i = reinterpret_cast<PrivateIdentifier*>(identifier);
    return i->isString;
}

NPUTF8 *NPN_UTF8FromIdentifier(NPIdentifier identifier) {
    PrivateIdentifier* i = reinterpret_cast<PrivateIdentifier*>(identifier);
    if (!i->isString || !i->value.string)
        return NULL;

    return (NPUTF8 *)strdup(i->value.string);
}

int32_t NPN_IntFromIdentifier(NPIdentifier identifier) {
    PrivateIdentifier* i = reinterpret_cast<PrivateIdentifier*>(identifier);
    if (i->isString)
        return 0;
    return i->value.number;
}

void NPN_ReleaseVariantValue(NPVariant* variant) {
    ASSERT(variant);

    if (variant->type == NPVariantType_Object) {
        NPN_ReleaseObject(variant->value.objectValue);
        variant->value.objectValue = 0;
    } else if (variant->type == NPVariantType_String) {
        free((void*)variant->value.stringValue.UTF8Characters);
        variant->value.stringValue.UTF8Characters = 0;
        variant->value.stringValue.UTF8Length = 0;
    }

    variant->type = NPVariantType_Void;
}

NPObject *NPN_CreateObject(NPP npp, NPClass* aClass) {
    ASSERT(aClass);

    if (aClass) {
        NPObject* obj;
        if (aClass->allocate != NULL)
            obj = aClass->allocate(npp, aClass);
        else
            obj = reinterpret_cast<NPObject*>(malloc(sizeof(NPObject)));

        obj->_class = aClass;
        obj->referenceCount = 1;
        return obj;
    }

    return 0;
}

NPObject* NPN_RetainObject(NPObject* obj) {
    ASSERT(obj);
    ASSERT(obj->referenceCount > 0);

    if (obj)
        obj->referenceCount++;

    return obj;
}

// _NPN_DeallocateObject actually deletes the object.  Technically,
// callers should use NPN_ReleaseObject.  Webkit exposes this function
// to kill objects which plugins may not have properly released.
void _NPN_DeallocateObject(NPObject *obj) {
    ASSERT(obj);
    ASSERT(obj->referenceCount >= 0);

    if (obj) {
        // NPObjects that remain in pure C++ may never have wrappers.
        // Hence, if it's not already alive, don't unregister it.
        // If it is alive, unregister it as the *last* thing we do
        // so that it can do as much cleanup as possible on its own.
        if (_NPN_IsAlive(obj))
            _NPN_UnregisterObject(obj);

        obj->referenceCount = -1;
        if (obj->_class->deallocate)
            obj->_class->deallocate(obj);
        else
            free(obj);
    }
}

void NPN_ReleaseObject(NPObject* obj) {
    ASSERT(obj);
    ASSERT(obj->referenceCount >= 1);

    if (obj && obj->referenceCount >= 1) {
        if (--obj->referenceCount == 0)
            _NPN_DeallocateObject(obj);
    }
}

void _NPN_InitializeVariantWithStringCopy(NPVariant* variant,
                                          const NPString* value) {
    variant->type = NPVariantType_String;
    variant->value.stringValue.UTF8Length = value->UTF8Length;
    variant->value.stringValue.UTF8Characters =
        reinterpret_cast<NPUTF8*>(malloc(sizeof(NPUTF8) * value->UTF8Length));
    memcpy((void*)variant->value.stringValue.UTF8Characters,
           value->UTF8Characters,
           sizeof(NPUTF8) * value->UTF8Length);
}

// NPN_Registry
//
// The registry is designed for quick lookup of NPObjects.
// JS needs to be able to quickly lookup a given NPObject to determine
// if it is alive or not.
// The browser needs to be able to quickly lookup all NPObjects which are
// "owned" by an object.
//
// The g_live_objects is a hash table of all live objects to their owner
// objects.  Presence in this table is used primarily to determine if
// objects are live or not.
//
// The g_root_objects is a hash table of root objects to a set of
// objects that should be deactivated in sync with the root.  A
// root is defined as a top-level owner object.  This is used on
// Frame teardown to deactivate all objects associated
// with a particular plugin.

typedef WTF::HashSet<NPObject*> NPObjectSet;
typedef WTF::HashMap<NPObject*, NPObject*> NPObjectMap;
typedef WTF::HashMap<NPObject*, NPObjectSet*> NPRootObjectMap;

// A map of live NPObjects with pointers to their Roots.
NPObjectMap g_live_objects;

// A map of the root objects and the list of NPObjects
// associated with that object.
NPRootObjectMap g_root_objects;

void _NPN_RegisterObject(NPObject* obj, NPObject* owner) {
    ASSERT(obj);

    // Check if already registered.
    if (g_live_objects.find(obj) != g_live_objects.end()) {
      return;
    }

    if (!owner) {
      // Registering a new owner object.
      ASSERT(g_root_objects.find(obj) == g_root_objects.end());
      g_root_objects.set(obj, new NPObjectSet());
    } else {
      // Always associate this object with it's top-most parent.
      // Since we always flatten, we only have to look up one level.
      NPObjectMap::iterator owner_entry = g_live_objects.find(owner);
      NPObject* parent = NULL;
      if (g_live_objects.end() != owner_entry)
          parent = owner_entry->second;

      if (parent) {
          owner = parent;
      }
      ASSERT(g_root_objects.find(obj) == g_root_objects.end());
      if (g_root_objects.find(owner) != g_root_objects.end())
          g_root_objects.get(owner)->add(obj);
    }

    ASSERT(g_live_objects.find(obj) == g_live_objects.end());
    g_live_objects.set(obj, owner);
}

void _NPN_UnregisterObject(NPObject* obj) {
    ASSERT(obj);
    ASSERT(g_live_objects.find(obj) != g_live_objects.end());

    NPObject* owner = NULL;
    if (g_live_objects.find(obj) != g_live_objects.end())
      owner = g_live_objects.find(obj)->second;

    if (owner == NULL) {
        // Unregistering a owner object; also unregister it's descendants.
        ASSERT(g_root_objects.find(obj) != g_root_objects.end());
        NPObjectSet* set = g_root_objects.get(obj);
        while (set->size() > 0) {
#ifndef NDEBUG
            int size = set->size();
#endif
            NPObject* sub_object = *(set->begin());
            // The sub-object should not be a owner!
            ASSERT(g_root_objects.find(sub_object) == g_root_objects.end());

            // First, unregister the object.
            set->remove(sub_object);
            g_live_objects.remove(sub_object);

            // Remove the JS references to the object.
            ForgetV8ObjectForNPObject(sub_object);

            ASSERT(set->size() < size);
        }
        delete set;
        g_root_objects.remove(obj);
    } else {
        NPRootObjectMap::iterator owner_entry = g_root_objects.find(owner);
        if (owner_entry != g_root_objects.end()) {
          NPObjectSet* list = owner_entry->second;
          ASSERT(list->find(obj) != list->end());
          list->remove(obj);
        }
    }
    ForgetV8ObjectForNPObject(obj);

    g_live_objects.remove(obj);
}

bool _NPN_IsAlive(NPObject* obj) {
    return g_live_objects.find(obj) != g_live_objects.end();
}

}  // extern "C"
<commit_msg>Fix issue 11264<commit_after>/*
 * Copyright (C) 2004, 2006 Apple Computer, Inc.  All rights reserved.
 * Copyright (C) 2007-2009 Google, Inc.  All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * 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 "NPV8Object.h"
#include "npruntime_priv.h"
#include "V8NPObject.h"

#include <wtf/HashMap.h>
#include <wtf/HashSet.h>
#include <wtf/Assertions.h>

// FIXME: Consider removing locks if we're singlethreaded already.
// The static initializer here should work okay, but we want to avoid
// static initialization in general.
//
// Commenting out the locks to avoid dependencies on chrome for now.
// Need a platform abstraction which we can use.
// static Lock StringIdentifierMapLock;

namespace {

// We use StringKey here as the key-type to avoid a string copy to
// construct the map key and for faster comparisons than strcmp.
class StringKey {
  public:
    explicit StringKey(const char* str)
        : m_string(str), m_length(strlen(str)) {}
    StringKey() : m_string(0), m_length(0) {}
    explicit StringKey(WTF::HashTableDeletedValueType)
        : m_string(hashTableDeletedValue()), m_length(0) { }

    StringKey& operator=(const StringKey& other) {
        this->m_string = other.m_string;
        this->m_length = other.m_length;
        return *this;
    }

    bool isHashTableDeletedValue() const {
        return m_string == hashTableDeletedValue();
    }

    const char* m_string;
    size_t m_length;
  private:
    const char* hashTableDeletedValue() const {
        return reinterpret_cast<const char*>(-1);
    }
};

inline bool operator==(const StringKey& x, const StringKey& y) {
    if (x.m_length != y.m_length) {
        return false;
    } else if (x.m_string == y.m_string) {
        return true;
    } else {
        ASSERT(!x.isHashTableDeletedValue() && !y.isHashTableDeletedValue());
        return memcmp(x.m_string, y.m_string, y.m_length) == 0;
    }
}

// Implement WTF::DefaultHash<StringKey>::Hash interface.
struct StringKeyHash {
    static unsigned hash(const StringKey& key) {
        // Compute string hash.
        unsigned hash = 0;
        size_t len = key.m_length;
        const char* str = key.m_string;
        for (size_t i = 0; i < len; i++) {
            char c = str[i];
            hash += c;
            hash += (hash << 10);
            hash ^= (hash >> 6);
        }
        hash += (hash << 3);
        hash ^= (hash >> 11);
        hash += (hash << 15);
        if (hash == 0) {
            hash = 27;
        }
        return hash;
    }

    static bool equal(const StringKey& x, const StringKey& y) {
        return x == y;
    }

    static const bool safeToCompareToEmptyOrDeleted = true;
};

}  // namespace

// Implement HashTraits<StringKey>
struct StringKeyHashTraits : WTF::GenericHashTraits<StringKey> {
    static void constructDeletedValue(StringKey& slot) {
        new (&slot) StringKey(WTF::HashTableDeletedValue);
    }
    static bool isDeletedValue(const StringKey& value) {
        return value.isHashTableDeletedValue();
    }
};

typedef WTF::HashMap<StringKey, PrivateIdentifier*, \
        StringKeyHash, StringKeyHashTraits> StringIdentifierMap;

static StringIdentifierMap* getStringIdentifierMap() {
    static StringIdentifierMap* stringIdentifierMap = 0;
    if (!stringIdentifierMap)
        stringIdentifierMap = new StringIdentifierMap();
    return stringIdentifierMap;
}

// FIXME: Consider removing locks if we're singlethreaded already.
// static Lock IntIdentifierMapLock;

typedef WTF::HashMap<int, PrivateIdentifier*> IntIdentifierMap;

static IntIdentifierMap* getIntIdentifierMap() {
    static IntIdentifierMap* intIdentifierMap = 0;
    if (!intIdentifierMap)
        intIdentifierMap = new IntIdentifierMap();
    return intIdentifierMap;
}

extern "C" {

NPIdentifier NPN_GetStringIdentifier(const NPUTF8* name) {
    ASSERT(name);

    if (name) {
        // AutoLock safeLock(StringIdentifierMapLock);

        StringKey key(name);
        StringIdentifierMap* identMap = getStringIdentifierMap();
        StringIdentifierMap::iterator iter = identMap->find(key);
        if (iter != identMap->end())
            return static_cast<NPIdentifier>(iter->second);

        size_t nameLen = key.m_length;

        // We never release identifiers, so this dictionary will grow.
        PrivateIdentifier* identifier = static_cast<PrivateIdentifier*>(
            malloc(sizeof(PrivateIdentifier) + nameLen + 1));
        char* nameStorage = reinterpret_cast<char*>(identifier + 1);
        memcpy(nameStorage, name, nameLen + 1);
        identifier->isString = true;
        identifier->value.string = reinterpret_cast<NPUTF8*>(nameStorage);
        key.m_string = nameStorage;
        identMap->set(key, identifier);
        return (NPIdentifier)identifier;
    }

    return 0;
}

void NPN_GetStringIdentifiers(const NPUTF8** names, int32_t nameCount,
                              NPIdentifier* identifiers) {
    ASSERT(names);
    ASSERT(identifiers);

    if (names && identifiers)
        for (int i = 0; i < nameCount; i++)
            identifiers[i] = NPN_GetStringIdentifier(names[i]);
}

NPIdentifier NPN_GetIntIdentifier(int32_t intid) {
    // AutoLock safeLock(IntIdentifierMapLock);
    // Special case for -1 and 0, both cannot be used as key in HashMap.
    if (intid == 0 || intid == -1) {
        static PrivateIdentifier* minusOneOrZeroIds[2];
        PrivateIdentifier* id = minusOneOrZeroIds[intid + 1];
        if (!id) {
            id = reinterpret_cast<PrivateIdentifier*>(
                malloc(sizeof(PrivateIdentifier)));
            id->isString = false;
            id->value.number = intid;
            minusOneOrZeroIds[intid + 1] = id;
        }
        return (NPIdentifier)id;
    }

    IntIdentifierMap* identMap = getIntIdentifierMap();
    IntIdentifierMap::iterator iter = identMap->find(intid);
    if (iter != identMap->end())
        return static_cast<NPIdentifier>(iter->second);

    // We never release identifiers, so this dictionary will grow.
    PrivateIdentifier* identifier = reinterpret_cast<PrivateIdentifier*>(
        malloc(sizeof(PrivateIdentifier)));
    identifier->isString = false;
    identifier->value.number = intid;
    identMap->set(intid, identifier);
    return (NPIdentifier)identifier;
}

bool NPN_IdentifierIsString(NPIdentifier identifier) {
    PrivateIdentifier* i = reinterpret_cast<PrivateIdentifier*>(identifier);
    return i->isString;
}

NPUTF8 *NPN_UTF8FromIdentifier(NPIdentifier identifier) {
    PrivateIdentifier* i = reinterpret_cast<PrivateIdentifier*>(identifier);
    if (!i->isString || !i->value.string)
        return NULL;

    return (NPUTF8 *)strdup(i->value.string);
}

int32_t NPN_IntFromIdentifier(NPIdentifier identifier) {
    PrivateIdentifier* i = reinterpret_cast<PrivateIdentifier*>(identifier);
    if (i->isString)
        return 0;
    return i->value.number;
}

void NPN_ReleaseVariantValue(NPVariant* variant) {
    ASSERT(variant);

    if (variant->type == NPVariantType_Object) {
        NPN_ReleaseObject(variant->value.objectValue);
        variant->value.objectValue = 0;
    } else if (variant->type == NPVariantType_String) {
        free((void*)variant->value.stringValue.UTF8Characters);
        variant->value.stringValue.UTF8Characters = 0;
        variant->value.stringValue.UTF8Length = 0;
    }

    variant->type = NPVariantType_Void;
}

NPObject *NPN_CreateObject(NPP npp, NPClass* aClass) {
    ASSERT(aClass);

    if (aClass) {
        NPObject* obj;
        if (aClass->allocate != NULL)
            obj = aClass->allocate(npp, aClass);
        else
            obj = reinterpret_cast<NPObject*>(malloc(sizeof(NPObject)));

        obj->_class = aClass;
        obj->referenceCount = 1;
        return obj;
    }

    return 0;
}

NPObject* NPN_RetainObject(NPObject* obj) {
    ASSERT(obj);
    ASSERT(obj->referenceCount > 0);

    if (obj)
        obj->referenceCount++;

    return obj;
}

// _NPN_DeallocateObject actually deletes the object.  Technically,
// callers should use NPN_ReleaseObject.  Webkit exposes this function
// to kill objects which plugins may not have properly released.
void _NPN_DeallocateObject(NPObject *obj) {
    ASSERT(obj);
    ASSERT(obj->referenceCount >= 0);

    if (obj) {
        // NPObjects that remain in pure C++ may never have wrappers.
        // Hence, if it's not already alive, don't unregister it.
        // If it is alive, unregister it as the *last* thing we do
        // so that it can do as much cleanup as possible on its own.
        if (_NPN_IsAlive(obj))
            _NPN_UnregisterObject(obj);

        obj->referenceCount = -1;
        if (obj->_class->deallocate)
            obj->_class->deallocate(obj);
        else
            free(obj);
    }
}

void NPN_ReleaseObject(NPObject* obj) {
    ASSERT(obj);
    ASSERT(obj->referenceCount >= 1);

    if (obj && obj->referenceCount >= 1) {
        if (--obj->referenceCount == 0)
            _NPN_DeallocateObject(obj);
    }
}

void _NPN_InitializeVariantWithStringCopy(NPVariant* variant,
                                          const NPString* value) {
    variant->type = NPVariantType_String;
    variant->value.stringValue.UTF8Length = value->UTF8Length;
    variant->value.stringValue.UTF8Characters =
        reinterpret_cast<NPUTF8*>(malloc(sizeof(NPUTF8) * value->UTF8Length));
    memcpy((void*)variant->value.stringValue.UTF8Characters,
           value->UTF8Characters,
           sizeof(NPUTF8) * value->UTF8Length);
}

// NPN_Registry
//
// The registry is designed for quick lookup of NPObjects.
// JS needs to be able to quickly lookup a given NPObject to determine
// if it is alive or not.
// The browser needs to be able to quickly lookup all NPObjects which are
// "owned" by an object.
//
// The g_live_objects is a hash table of all live objects to their owner
// objects.  Presence in this table is used primarily to determine if
// objects are live or not.
//
// The g_root_objects is a hash table of root objects to a set of
// objects that should be deactivated in sync with the root.  A
// root is defined as a top-level owner object.  This is used on
// Frame teardown to deactivate all objects associated
// with a particular plugin.

typedef WTF::HashSet<NPObject*> NPObjectSet;
typedef WTF::HashMap<NPObject*, NPObject*> NPObjectMap;
typedef WTF::HashMap<NPObject*, NPObjectSet*> NPRootObjectMap;

// A map of live NPObjects with pointers to their Roots.
NPObjectMap g_live_objects;

// A map of the root objects and the list of NPObjects
// associated with that object.
NPRootObjectMap g_root_objects;

void _NPN_RegisterObject(NPObject* obj, NPObject* owner) {
    ASSERT(obj);

    // Check if already registered.
    if (g_live_objects.find(obj) != g_live_objects.end()) {
      return;
    }

    if (!owner) {
      // Registering a new owner object.
      ASSERT(g_root_objects.find(obj) == g_root_objects.end());
      g_root_objects.set(obj, new NPObjectSet());
    } else {
      // Always associate this object with it's top-most parent.
      // Since we always flatten, we only have to look up one level.
      NPObjectMap::iterator owner_entry = g_live_objects.find(owner);
      NPObject* parent = NULL;
      if (g_live_objects.end() != owner_entry)
          parent = owner_entry->second;

      if (parent) {
          owner = parent;
      }
      ASSERT(g_root_objects.find(obj) == g_root_objects.end());
      if (g_root_objects.find(owner) != g_root_objects.end())
          g_root_objects.get(owner)->add(obj);
    }

    ASSERT(g_live_objects.find(obj) == g_live_objects.end());
    g_live_objects.set(obj, owner);
}

void _NPN_UnregisterObject(NPObject* obj) {
    ASSERT(obj);
    ASSERT(g_live_objects.find(obj) != g_live_objects.end());

    NPObject* owner = NULL;
    if (g_live_objects.find(obj) != g_live_objects.end())
      owner = g_live_objects.find(obj)->second;

    if (owner == NULL) {
        // Unregistering a owner object; also unregister it's descendants.
        ASSERT(g_root_objects.find(obj) != g_root_objects.end());
        NPObjectSet* set = g_root_objects.get(obj);
        while (set->size() > 0) {
#ifndef NDEBUG
            int size = set->size();
#endif
            NPObject* sub_object = *(set->begin());
            // The sub-object should not be a owner!
            ASSERT(g_root_objects.find(sub_object) == g_root_objects.end());

            // First, unregister the object.
            set->remove(sub_object);
            g_live_objects.remove(sub_object);

            // Remove the JS references to the object.
            ForgetV8ObjectForNPObject(sub_object);

            ASSERT(set->size() < size);
        }
        delete set;
        g_root_objects.remove(obj);
    } else {
        NPRootObjectMap::iterator owner_entry = g_root_objects.find(owner);
        if (owner_entry != g_root_objects.end()) {
          NPObjectSet* list = owner_entry->second;
          ASSERT(list->find(obj) != list->end());
          list->remove(obj);
        }
    }
    ForgetV8ObjectForNPObject(obj);

    g_live_objects.remove(obj);
}

bool _NPN_IsAlive(NPObject* obj) {
    return g_live_objects.find(obj) != g_live_objects.end();
}

}  // extern "C"
<|endoftext|>


<commit_before>#include <limits>
#include "RayTracer.h"
#include "Image.h"
#include "Object.h"
#include "Sphere.h"
#include "Intersection.h"
#include "Light.h"

using namespace std;

RayTracer::RayTracer(int width_, int height_, int maxReflections_, int superSamples_,
 int depthComplexity_) : width(width_), height(height_),
 maxReflections(maxReflections_), superSamples(superSamples_),
 depthComplexity(depthComplexity_) {
   cameraPosition = Vector(0.0, 0.0, 100.0);
   focalPointLength = 100.0;
   dispersion = 5.0f;
}

RayTracer::~RayTracer() {
   for (vector<Object*>::iterator itr = objects.begin(); itr < objects.end(); itr++) {
      delete *itr;
   }

   for (vector<Light*>::iterator itr = lights.begin(); itr < lights.end(); itr++) {
      delete *itr;
   }
}

void RayTracer::traceRays(string fileName) {
   Image image(width, height);

   for (int x = 0; x < width; x++) {
      // Update percent complete.
      float percentage = x/(float)width * 100;
      cout << '\r' << (int)percentage << '%';
      fflush(stdout);

      for (int y = 0; y < height; y++) {
         image.pixel(x, y, castRayForPixel(x, y));
      }
   }

   cout << "\rDone!" << endl;

   image.WriteTga(fileName.c_str(), false);
}

Color RayTracer::castRayForPixel(int x, int y) {
   /**
    * All of these values are "on the focal plane." That is to say rays will
    * be cast from the camera position towards points created from these
    * values.
    */
   double rayX = (x - width / 2)/2.0;
   double rayY = (y - height / 2)/2.0;
   double pixelWidth = rayX - (x + 1 - width / 2)/2.0;
   double sampleWidth = pixelWidth / superSamples;
   double sampleStartX = rayX - pixelWidth/2.0;
   double sampleStartY = rayY - pixelWidth/2.0;
   double sampleWeight = 1.0 / (superSamples * superSamples);
   Color color;

   for (int x = 0; x < superSamples; x++) {
      for (int y = 0; y < superSamples; y++) {
         Vector imagePlanePoint = Vector(sampleStartX + (x * sampleWidth),
          sampleStartY + (y * sampleWidth), 0);

         color = color + (castRayWithXY(imagePlanePoint) * sampleWeight);
      }
   }

   return color;
}

Color RayTracer::castRayWithXY(Vector direction) {
   Color color;
   // Divide by projection distance.
   direction.x /= 500.0;
   direction.y /= 500.0;
   direction.z = -1;

   direction = direction.normalize();
   Vector aimed = cameraPosition + (direction * focalPointLength);

   for (int i = 0; i < depthComplexity; i++) {
      Ray viewRay(cameraPosition, direction, maxReflections);

      if (depthComplexity > 1 && dispersion > 0) {
         Vector disturbance(
          (dispersion / RAND_MAX) * (1.0f * rand()),
          (dispersion / RAND_MAX) * (1.0f * rand()),
          0.0f);

         viewRay.origin = viewRay.origin + disturbance;
         viewRay.direction = aimed - viewRay.origin;
         viewRay.direction = viewRay.direction.normalize();
      }

      color = color + (castRay(viewRay) * (1 / (float)depthComplexity));
   }

   return color;
}

Color RayTracer::castRay(Ray ray) {
   Intersection intersection = getClosestIntersection(ray);

   if (intersection.didIntersect) {
      return performLighting(intersection);
   } else {
      return Color();
   }
}

Intersection RayTracer::getClosestIntersection(Ray ray) {
   Intersection closestIntersection(false);
   closestIntersection.distance = numeric_limits<double>::max();

   for (vector<Object*>::iterator itr = objects.begin(); itr < objects.end(); itr++) {
      Intersection intersection = (*itr)->intersect(ray);

      if (intersection.didIntersect && intersection.distance <
       closestIntersection.distance) {
         closestIntersection = intersection;
      }
   }

   return closestIntersection;
}

Color RayTracer::performLighting(Intersection intersection) {
   Color ambientColor = getAmbientLighting(intersection);
   Color diffuseAndSpecularColor = getDiffuseAndSpecularLighting(intersection);
   Color reflectedColor = getReflectiveLighting(intersection);

   return ambientColor + diffuseAndSpecularColor + reflectedColor;
}

Color RayTracer::getAmbientLighting(Intersection intersection) {
   return intersection.color * 0.2;
}

Color RayTracer::getDiffuseAndSpecularLighting(Intersection intersection) {
   Color diffuseColor(0.0, 0.0, 0.0);
   Color specularColor(0.0, 0.0, 0.0);

   for (vector<Light*>::iterator itr = lights.begin(); itr < lights.end(); itr++) {
      Light* light = *itr;
      Vector lightOffset = light->position - intersection.intersection;
      /**
       * TODO: Be careful about normalizing lightOffset too.
       */
      Vector lightDirection = lightOffset.normalize();
      double dotProduct = intersection.normal.dot(lightDirection);

      /**
       * Intersection is facing light.
       */
      if (dotProduct >= 0.0f) {
         Ray shadowRay = Ray(intersection.intersection, lightDirection, 1);
         Intersection shadowIntersection = getClosestIntersection(shadowRay);

         if (shadowIntersection.didIntersect) {
            /**
             * Position is in shadow of another object - continue with other lights.
             */
            continue;
         }

         diffuseColor = (diffuseColor + (intersection.color * dotProduct)) *
          light->intensity;
         specularColor = specularColor + getSpecularLighting(intersection, light);
      }
   }

   return diffuseColor + specularColor;
}

Color RayTracer::getSpecularLighting(Intersection intersection, Light* light) {
   Color specularColor(0.0, 0.0, 0.0);
   double shininess = intersection.object->getShininess();

   if (shininess == NOT_SHINY) {
      /* Don't perform specular lighting on non shiny objects. */
      return specularColor;
   }

   Vector view = (intersection.ray.origin - intersection.intersection).normalize();
   Vector lightOffset = light->position - intersection.intersection;
   Vector reflected = reflectVector(lightOffset.normalize(), intersection.normal);

   double dot = view.dot(reflected);

   if (dot <= 0) {
      return specularColor;
   }

   double specularAmount = pow(dot, shininess) * light->intensity;

   specularColor.r = specularAmount;
   specularColor.g = specularAmount;
   specularColor.b = specularAmount;

   return specularColor;
}

Color RayTracer::getReflectiveLighting(Intersection intersection) {
   double reflectivity = intersection.object->getReflectivity();
   int reflectionsRemaining = intersection.ray.reflectionsRemaining;

   if (reflectivity == NOT_REFLECTIVE || reflectionsRemaining <= 0) {
      return Color();
   } else {
      Vector reflected = reflectVector(intersection.ray.origin, intersection.normal);
      Ray reflectedRay(intersection.intersection, reflected, reflectionsRemaining - 1);

      return castRay(reflectedRay) * reflectivity;
   }
}

Vector RayTracer::reflectVector(Vector vector, Vector normal) {
   return normal * 2 * vector.dot(normal) - vector;
}

void RayTracer::readScene(istream& in) {
   string type;

   in >> type;

   while (in.good()) {
      if (type.compare("sphere") == 0) {
         Vector center;
         double radius;
         Color color;
         double shininess;
         double reflectivity;

         in >> center.x >> center.y >> center.z;
         in >> radius;
         in >> color.r >> color.g >> color.b;
         in >> shininess;
         in >> reflectivity;

         addObject(new Sphere(center, radius, color, shininess, reflectivity));
      } else if (type.compare("light") == 0) {
         Vector position;
         double intensity;

         in >> position.x >> position.y >> position.z;
         in >> intensity;

         addLight(new Light(position, intensity));
      } else if (type.compare("dispersion") == 0) {
         in >> dispersion;
      } else if (type.compare("maxReflections") == 0) {
         in >> maxReflections;
      } else if (type.compare("cameraPosition") == 0) {
         in >> cameraPosition.z;
      } else if (type.compare("focus") == 0) {
         in >> focalPointLength;
      } else {
         cerr << "Type not found: " << type << endl;
         exit(EXIT_FAILURE);
      }

      in >> type;
   }
}

<commit_msg>Add support for disabling depth of field<commit_after>#include <limits>
#include "RayTracer.h"
#include "Image.h"
#include "Object.h"
#include "Sphere.h"
#include "Intersection.h"
#include "Light.h"

using namespace std;

RayTracer::RayTracer(int width_, int height_, int maxReflections_, int superSamples_,
 int depthComplexity_) : width(width_), height(height_),
 maxReflections(maxReflections_), superSamples(superSamples_),
 depthComplexity(depthComplexity_) {
   cameraPosition = Vector(0.0, 0.0, 100.0);
   focalPointLength = 100.0;
   dispersion = 5.0f;
}

RayTracer::~RayTracer() {
   for (vector<Object*>::iterator itr = objects.begin(); itr < objects.end(); itr++) {
      delete *itr;
   }

   for (vector<Light*>::iterator itr = lights.begin(); itr < lights.end(); itr++) {
      delete *itr;
   }
}

void RayTracer::traceRays(string fileName) {
   Image image(width, height);

   // Reset depthComplexity to avoid unnecessary loops.
   if (dispersion < 0) {
      depthComplexity = 1;
   }

   for (int x = 0; x < width; x++) {
      // Update percent complete.
      float percentage = x/(float)width * 100;
      cout << '\r' << (int)percentage << '%';
      fflush(stdout);

      for (int y = 0; y < height; y++) {
         image.pixel(x, y, castRayForPixel(x, y));
      }
   }

   cout << "\rDone!" << endl;

   image.WriteTga(fileName.c_str(), false);
}

Color RayTracer::castRayForPixel(int x, int y) {
   /**
    * All of these values are "on the focal plane." That is to say rays will
    * be cast from the camera position towards points created from these
    * values.
    */
   double rayX = (x - width / 2)/2.0;
   double rayY = (y - height / 2)/2.0;
   double pixelWidth = rayX - (x + 1 - width / 2)/2.0;
   double sampleWidth = pixelWidth / superSamples;
   double sampleStartX = rayX - pixelWidth/2.0;
   double sampleStartY = rayY - pixelWidth/2.0;
   double sampleWeight = 1.0 / (superSamples * superSamples);
   Color color;

   for (int x = 0; x < superSamples; x++) {
      for (int y = 0; y < superSamples; y++) {
         Vector imagePlanePoint = Vector(sampleStartX + (x * sampleWidth),
          sampleStartY + (y * sampleWidth), 0);

         color = color + (castRayWithXY(imagePlanePoint) * sampleWeight);
      }
   }

   return color;
}

Color RayTracer::castRayWithXY(Vector direction) {
   Color color;
   // Divide by projection distance.
   direction.x /= 500.0;
   direction.y /= 500.0;
   direction.z = -1;

   direction = direction.normalize();
   Vector aimed = cameraPosition + (direction * focalPointLength);

   for (int i = 0; i < depthComplexity; i++) {
      Ray viewRay(cameraPosition, direction, maxReflections);

      if (depthComplexity > 1) {
         Vector disturbance(
          (dispersion / RAND_MAX) * (1.0f * rand()),
          (dispersion / RAND_MAX) * (1.0f * rand()),
          0.0f);

         viewRay.origin = viewRay.origin + disturbance;
         viewRay.direction = aimed - viewRay.origin;
         viewRay.direction = viewRay.direction.normalize();
      }

      color = color + (castRay(viewRay) * (1 / (float)depthComplexity));
   }

   return color;
}

Color RayTracer::castRay(Ray ray) {
   Intersection intersection = getClosestIntersection(ray);

   if (intersection.didIntersect) {
      return performLighting(intersection);
   } else {
      return Color();
   }
}

Intersection RayTracer::getClosestIntersection(Ray ray) {
   Intersection closestIntersection(false);
   closestIntersection.distance = numeric_limits<double>::max();

   for (vector<Object*>::iterator itr = objects.begin(); itr < objects.end(); itr++) {
      Intersection intersection = (*itr)->intersect(ray);

      if (intersection.didIntersect && intersection.distance <
       closestIntersection.distance) {
         closestIntersection = intersection;
      }
   }

   return closestIntersection;
}

Color RayTracer::performLighting(Intersection intersection) {
   Color ambientColor = getAmbientLighting(intersection);
   Color diffuseAndSpecularColor = getDiffuseAndSpecularLighting(intersection);
   Color reflectedColor = getReflectiveLighting(intersection);

   return ambientColor + diffuseAndSpecularColor + reflectedColor;
}

Color RayTracer::getAmbientLighting(Intersection intersection) {
   return intersection.color * 0.2;
}

Color RayTracer::getDiffuseAndSpecularLighting(Intersection intersection) {
   Color diffuseColor(0.0, 0.0, 0.0);
   Color specularColor(0.0, 0.0, 0.0);

   for (vector<Light*>::iterator itr = lights.begin(); itr < lights.end(); itr++) {
      Light* light = *itr;
      Vector lightOffset = light->position - intersection.intersection;
      /**
       * TODO: Be careful about normalizing lightOffset too.
       */
      Vector lightDirection = lightOffset.normalize();
      double dotProduct = intersection.normal.dot(lightDirection);

      /**
       * Intersection is facing light.
       */
      if (dotProduct >= 0.0f) {
         Ray shadowRay = Ray(intersection.intersection, lightDirection, 1);
         Intersection shadowIntersection = getClosestIntersection(shadowRay);

         if (shadowIntersection.didIntersect) {
            /**
             * Position is in shadow of another object - continue with other lights.
             */
            continue;
         }

         diffuseColor = (diffuseColor + (intersection.color * dotProduct)) *
          light->intensity;
         specularColor = specularColor + getSpecularLighting(intersection, light);
      }
   }

   return diffuseColor + specularColor;
}

Color RayTracer::getSpecularLighting(Intersection intersection, Light* light) {
   Color specularColor(0.0, 0.0, 0.0);
   double shininess = intersection.object->getShininess();

   if (shininess == NOT_SHINY) {
      /* Don't perform specular lighting on non shiny objects. */
      return specularColor;
   }

   Vector view = (intersection.ray.origin - intersection.intersection).normalize();
   Vector lightOffset = light->position - intersection.intersection;
   Vector reflected = reflectVector(lightOffset.normalize(), intersection.normal);

   double dot = view.dot(reflected);

   if (dot <= 0) {
      return specularColor;
   }

   double specularAmount = pow(dot, shininess) * light->intensity;

   specularColor.r = specularAmount;
   specularColor.g = specularAmount;
   specularColor.b = specularAmount;

   return specularColor;
}

Color RayTracer::getReflectiveLighting(Intersection intersection) {
   double reflectivity = intersection.object->getReflectivity();
   int reflectionsRemaining = intersection.ray.reflectionsRemaining;

   if (reflectivity == NOT_REFLECTIVE || reflectionsRemaining <= 0) {
      return Color();
   } else {
      Vector reflected = reflectVector(intersection.ray.origin, intersection.normal);
      Ray reflectedRay(intersection.intersection, reflected, reflectionsRemaining - 1);

      return castRay(reflectedRay) * reflectivity;
   }
}

Vector RayTracer::reflectVector(Vector vector, Vector normal) {
   return normal * 2 * vector.dot(normal) - vector;
}

void RayTracer::readScene(istream& in) {
   string type;

   in >> type;

   while (in.good()) {
      if (type.compare("sphere") == 0) {
         Vector center;
         double radius;
         Color color;
         double shininess;
         double reflectivity;

         in >> center.x >> center.y >> center.z;
         in >> radius;
         in >> color.r >> color.g >> color.b;
         in >> shininess;
         in >> reflectivity;

         addObject(new Sphere(center, radius, color, shininess, reflectivity));
      } else if (type.compare("light") == 0) {
         Vector position;
         double intensity;

         in >> position.x >> position.y >> position.z;
         in >> intensity;

         addLight(new Light(position, intensity));
      } else if (type.compare("dispersion") == 0) {
         in >> dispersion;
      } else if (type.compare("maxReflections") == 0) {
         in >> maxReflections;
      } else if (type.compare("cameraPosition") == 0) {
         in >> cameraPosition.z;
      } else if (type.compare("focus") == 0) {
         in >> focalPointLength;
      } else {
         cerr << "Type not found: " << type << endl;
         exit(EXIT_FAILURE);
      }

      in >> type;
   }
}

<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  $RCSfile: workingsetoptions.cxx,v $
 *
 *  $Revision: 1.4 $
 *
 *  last change: $Author: vg $ $Date: 2003-04-15 17:52:40 $
 *
 *  The Contents of this file are made available subject to the terms of
 *  either of the following licenses
 *
 *         - GNU Lesser General Public License Version 2.1
 *         - Sun Industry Standards Source License Version 1.1
 *
 *  Sun Microsystems Inc., October, 2000
 *
 *  GNU Lesser General Public License Version 2.1
 *  =============================================
 *  Copyright 2000 by Sun Microsystems, Inc.
 *  901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License version 2.1, as published by the Free Software Foundation.
 *
 *  This library is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *  Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this library; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *  MA  02111-1307  USA
 *
 *
 *  Sun Industry Standards Source License Version 1.1
 *  =================================================
 *  The contents of this file are subject to the Sun Industry Standards
 *  Source License Version 1.1 (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.openoffice.org/license.html.
 *
 *  Software provided under this License is provided on an "AS IS" basis,
 *  WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
 *  WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
 *  MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
 *  See the License for the specific provisions governing your rights and
 *  obligations concerning the Software.
 *
 *  The Initial Developer of the Original Code is: Sun Microsystems, Inc.
 *
 *  Copyright: 2000 by Sun Microsystems, Inc.
 *
 *  All Rights Reserved.
 *
 *  Contributor(s): _______________________________________
 *
 *
 ************************************************************************/

#pragma hdrstop

//_________________________________________________________________________________________________________________
//  includes
//_________________________________________________________________________________________________________________

#include "workingsetoptions.hxx"

#ifndef _UTL_CONFIGMGR_HXX_
#include <unotools/configmgr.hxx>
#endif

#ifndef _UTL_CONFIGITEM_HXX_
#include <unotools/configitem.hxx>
#endif

#ifndef _TOOLS_DEBUG_HXX
#include <tools/debug.hxx>
#endif

#ifndef _COM_SUN_STAR_UNO_ANY_HXX_
#include <com/sun/star/uno/Any.hxx>
#endif

#ifndef _COM_SUN_STAR_UNO_SEQUENCE_HXX_
#include <com/sun/star/uno/Sequence.hxx>
#endif

//_________________________________________________________________________________________________________________
//  namespaces
//_________________________________________________________________________________________________________________

using namespace ::utl                   ;
using namespace ::rtl                   ;
using namespace ::osl                   ;
using namespace ::com::sun::star::uno   ;

//_________________________________________________________________________________________________________________
//  const
//_________________________________________________________________________________________________________________

#define ROOTNODE_WORKINGSET             OUString(RTL_CONSTASCII_USTRINGPARAM("Office.Common/WorkingSet"))
#define DEFAULT_WINDOWLIST              Sequence< OUString >()

#define PROPERTYNAME_WINDOWLIST         OUString(RTL_CONSTASCII_USTRINGPARAM("WindowList"       ))

#define PROPERTYHANDLE_WINDOWLIST       0

#define PROPERTYCOUNT                   1

//_________________________________________________________________________________________________________________
//  private declarations!
//_________________________________________________________________________________________________________________

class SvtWorkingSetOptions_Impl : public ConfigItem
{
    //-------------------------------------------------------------------------------------------------------------
    //  public methods
    //-------------------------------------------------------------------------------------------------------------

    public:

        //---------------------------------------------------------------------------------------------------------
        //  constructor / destructor
        //---------------------------------------------------------------------------------------------------------

         SvtWorkingSetOptions_Impl();
        ~SvtWorkingSetOptions_Impl();

        //---------------------------------------------------------------------------------------------------------
        //  overloaded methods of baseclass
        //---------------------------------------------------------------------------------------------------------

        /*-****************************************************************************************************//**
            @short      called for notify of configmanager
            @descr      These method is called from the ConfigManager before application ends or from the
                         PropertyChangeListener if the sub tree broadcasts changes. You must update your
                        internal values.

            @seealso    baseclass ConfigItem

            @param      "seqPropertyNames" is the list of properties which should be updated.
            @return     -

            @onerror    -
        *//*-*****************************************************************************************************/

        virtual void Notify( const Sequence< OUString >& seqPropertyNames );

        /*-****************************************************************************************************//**
            @short      write changes to configuration
            @descr      These method writes the changed values into the sub tree
                        and should always called in our destructor to guarantee consistency of config data.

            @seealso    baseclass ConfigItem

            @param      -
            @return     -

            @onerror    -
        *//*-*****************************************************************************************************/

        virtual void Commit();

        //---------------------------------------------------------------------------------------------------------
        //  public interface
        //---------------------------------------------------------------------------------------------------------

        /*-****************************************************************************************************//**
            @short      access method to get internal values
            @descr      These method give us a chance to regulate acces to ouer internal values.
                        It's not used in the moment - but it's possible for the feature!

            @seealso    -

            @param      -
            @return     -

            @onerror    -
        *//*-*****************************************************************************************************/

        Sequence< OUString >    GetWindowList(                                              ) const ;
        void                    SetWindowList( const Sequence< OUString >&  seqWindowList   )       ;

    //-------------------------------------------------------------------------------------------------------------
    //  private methods
    //-------------------------------------------------------------------------------------------------------------

    private:

        /*-****************************************************************************************************//**
            @short      return list of key names of ouer configuration management which represent oue module tree
            @descr      These methods return a static const list of key names. We need it to get needed values from our
                        configuration management.

            @seealso    -

            @param      -
            @return     A list of needed configuration keys is returned.

            @onerror    -
        *//*-*****************************************************************************************************/

        static Sequence< OUString > GetPropertyNames();

    //-------------------------------------------------------------------------------------------------------------
    //  private member
    //-------------------------------------------------------------------------------------------------------------

    private:

        Sequence< OUString >    m_seqWindowList     ;
};

//_________________________________________________________________________________________________________________
//  definitions
//_________________________________________________________________________________________________________________

//*****************************************************************************************************************
//  constructor
//*****************************************************************************************************************
SvtWorkingSetOptions_Impl::SvtWorkingSetOptions_Impl()
    // Init baseclasses first
    :   ConfigItem          ( ROOTNODE_WORKINGSET   )
    // Init member then.
    ,   m_seqWindowList     ( DEFAULT_WINDOWLIST    )
{
    // Use our static list of configuration keys to get his values.
    Sequence< OUString >    seqNames    = GetPropertyNames  (           );
    Sequence< Any >         seqValues   = GetProperties     ( seqNames  );

    // Safe impossible cases.
    // We need values from ALL configuration keys.
    // Follow assignment use order of values in relation to our list of key names!
    DBG_ASSERT( !(seqNames.getLength()!=seqValues.getLength()), "SvtWorkingSetOptions_Impl::SvtWorkingSetOptions_Impl()\nI miss some values of configuration keys!\n" );

    // Copy values from list in right order to ouer internal member.
    sal_Int32 nPropertyCount = seqValues.getLength();
    for( sal_Int32 nProperty=0; nProperty<nPropertyCount; ++nProperty )
    {
        // Safe impossible cases.
        // Check any for valid value.
        DBG_ASSERT( !(seqValues[nProperty].hasValue()==sal_False), "SvtWorkingSetOptions_Impl::SvtWorkingSetOptions_Impl()\nInvalid property value detected!\n" );
        switch( nProperty )
        {
            case PROPERTYHANDLE_WINDOWLIST      :   {
                                                        DBG_ASSERT(!(seqValues[nProperty].getValueTypeClass()!=TypeClass_SEQUENCE), "SvtWorkingSetOptions_Impl::SvtWorkingSetOptions_Impl()\nWho has changed the value type of \"Office.Common\\WorkingSet\\WindowList\"?" );
                                                        seqValues[nProperty] >>= m_seqWindowList;
                                                    }
                                                    break;
        }
    }

    // Enable notification mechanism of ouer baseclass.
    // We need it to get information about changes outside these class on ouer used configuration keys!
    EnableNotification( seqNames );
}

//*****************************************************************************************************************
//  destructor
//*****************************************************************************************************************
SvtWorkingSetOptions_Impl::~SvtWorkingSetOptions_Impl()
{
    // We must save our current values .. if user forget it!
    if( IsModified() == sal_True )
    {
        Commit();
    }
}

//*****************************************************************************************************************
//  public method
//*****************************************************************************************************************
void SvtWorkingSetOptions_Impl::Notify( const Sequence< OUString >& seqPropertyNames )
{
    // Use given list of updated properties to get his values from configuration directly!
    Sequence< Any > seqValues = GetProperties( seqPropertyNames );
    // Safe impossible cases.
    // We need values from ALL notified configuration keys.
    DBG_ASSERT( !(seqPropertyNames.getLength()!=seqValues.getLength()), "SvtWorkingSetOptions_Impl::Notify()\nI miss some values of configuration keys!\n" );
    // Step over list of property names and get right value from coreesponding value list to set it on internal members!
    sal_Int32 nCount = seqPropertyNames.getLength();
    for( sal_Int32 nProperty=0; nProperty<nCount; ++nProperty )
    {
        if( seqPropertyNames[nProperty] == PROPERTYNAME_WINDOWLIST )
        {
            DBG_ASSERT(!(seqValues[nProperty].getValueTypeClass()!=TypeClass_SEQUENCE), "SvtWorkingSetOptions_Impl::Notify()\nWho has changed the value type of \"Office.Common\\WorkingSet\\WindowList\"?" );
            seqValues[nProperty] >>= m_seqWindowList;
        }
        #if OSL_DEBUG_LEVEL > 1
        else DBG_ASSERT( sal_False, "SvtWorkingSetOptions_Impl::Notify()\nUnkown property detected ... I can't handle these!\n" );
        #endif
    }
}

//*****************************************************************************************************************
//  public method
//*****************************************************************************************************************
void SvtWorkingSetOptions_Impl::Commit()
{
    // Get names of supported properties, create a list for values and copy current values to it.
    Sequence< OUString >    seqNames    = GetPropertyNames  ();
    sal_Int32               nCount      = seqNames.getLength();
    Sequence< Any >         seqValues   ( nCount );
    for( sal_Int32 nProperty=0; nProperty<nCount; ++nProperty )
    {
        switch( nProperty )
        {
            case PROPERTYHANDLE_WINDOWLIST      :   {
                                                        seqValues[nProperty] <<= m_seqWindowList;
                                                    }
                                                    break;
        }
    }
    // Set properties in configuration.
    PutProperties( seqNames, seqValues );
}

//*****************************************************************************************************************
//  public method
//*****************************************************************************************************************
Sequence< OUString > SvtWorkingSetOptions_Impl::GetWindowList() const
{
    return m_seqWindowList;
}

//*****************************************************************************************************************
//  public method
//*****************************************************************************************************************
void SvtWorkingSetOptions_Impl::SetWindowList( const Sequence< OUString >& seqWindowList )
{
    m_seqWindowList = seqWindowList;
    SetModified();
}

//*****************************************************************************************************************
//  private method
//*****************************************************************************************************************
Sequence< OUString > SvtWorkingSetOptions_Impl::GetPropertyNames()
{
    // Build static list of configuration key names.
    static const OUString pProperties[] =
    {
        PROPERTYNAME_WINDOWLIST ,
    };
    // Initialize return sequence with these list ...
    static const Sequence< OUString > seqPropertyNames( pProperties, PROPERTYCOUNT );
    // ... and return it.
    return seqPropertyNames;
}

//*****************************************************************************************************************
//  initialize static member
//  DON'T DO IT IN YOUR HEADER!
//  see definition for further informations
//*****************************************************************************************************************
SvtWorkingSetOptions_Impl*  SvtWorkingSetOptions::m_pDataContainer  = NULL  ;
sal_Int32                   SvtWorkingSetOptions::m_nRefCount       = 0     ;

//*****************************************************************************************************************
//  constructor
//*****************************************************************************************************************
SvtWorkingSetOptions::SvtWorkingSetOptions()
{
    // Global access, must be guarded (multithreading!).
    MutexGuard aGuard( GetOwnStaticMutex() );
    // Increase ouer refcount ...
    ++m_nRefCount;
    // ... and initialize ouer data container only if it not already exist!
    if( m_pDataContainer == NULL )
    {
        m_pDataContainer = new SvtWorkingSetOptions_Impl;
    }
}

//*****************************************************************************************************************
//  destructor
//*****************************************************************************************************************
SvtWorkingSetOptions::~SvtWorkingSetOptions()
{
    // Global access, must be guarded (multithreading!)
    MutexGuard aGuard( GetOwnStaticMutex() );
    // Decrease ouer refcount.
    --m_nRefCount;
    // If last instance was deleted ...
    // we must destroy ouer static data container!
    if( m_nRefCount <= 0 )
    {
        delete m_pDataContainer;
        m_pDataContainer = NULL;
    }
}

//*****************************************************************************************************************
//  public method
//*****************************************************************************************************************
Sequence< OUString > SvtWorkingSetOptions::GetWindowList() const
{
    MutexGuard aGuard( GetOwnStaticMutex() );
    return m_pDataContainer->GetWindowList();
}

//*****************************************************************************************************************
//  public method
//*****************************************************************************************************************
void SvtWorkingSetOptions::SetWindowList( const Sequence< OUString >& seqWindowList )
{
    MutexGuard aGuard( GetOwnStaticMutex() );
    m_pDataContainer->SetWindowList( seqWindowList );
}

//*****************************************************************************************************************
//  private method
//*****************************************************************************************************************
Mutex& SvtWorkingSetOptions::GetOwnStaticMutex()
{
    // Initialize static mutex only for one time!
    static Mutex* pMutex = NULL;
    // If these method first called (Mutex not already exist!) ...
    if( pMutex == NULL )
    {
        // ... we must create a new one. Protect follow code with the global mutex -
        // It must be - we create a static variable!
        MutexGuard aGuard( Mutex::getGlobalMutex() );
        // We must check our pointer again - because it can be that another instance of ouer class will be fastr then these!
        if( pMutex == NULL )
        {
            // Create the new mutex and set it for return on static variable.
            static Mutex aMutex;
            pMutex = &aMutex;
        }
    }
    // Return new created or already existing mutex object.
    return *pMutex;
}
<commit_msg>INTEGRATION: CWS ooo20040509 (1.4.384); FILE MERGED 2004/05/06 14:04:20 waratah 1.4.384.1: Bracket pragma not valid for gcc<commit_after>/*************************************************************************
 *
 *  $RCSfile: workingsetoptions.cxx,v $
 *
 *  $Revision: 1.5 $
 *
 *  last change: $Author: rt $ $Date: 2004-06-16 10:10:11 $
 *
 *  The Contents of this file are made available subject to the terms of
 *  either of the following licenses
 *
 *         - GNU Lesser General Public License Version 2.1
 *         - Sun Industry Standards Source License Version 1.1
 *
 *  Sun Microsystems Inc., October, 2000
 *
 *  GNU Lesser General Public License Version 2.1
 *  =============================================
 *  Copyright 2000 by Sun Microsystems, Inc.
 *  901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License version 2.1, as published by the Free Software Foundation.
 *
 *  This library is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *  Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this library; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *  MA  02111-1307  USA
 *
 *
 *  Sun Industry Standards Source License Version 1.1
 *  =================================================
 *  The contents of this file are subject to the Sun Industry Standards
 *  Source License Version 1.1 (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.openoffice.org/license.html.
 *
 *  Software provided under this License is provided on an "AS IS" basis,
 *  WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
 *  WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
 *  MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
 *  See the License for the specific provisions governing your rights and
 *  obligations concerning the Software.
 *
 *  The Initial Developer of the Original Code is: Sun Microsystems, Inc.
 *
 *  Copyright: 2000 by Sun Microsystems, Inc.
 *
 *  All Rights Reserved.
 *
 *  Contributor(s): _______________________________________
 *
 *
 ************************************************************************/
#ifndef GCC
#pragma hdrstop
#endif

//_________________________________________________________________________________________________________________
//  includes
//_________________________________________________________________________________________________________________

#include "workingsetoptions.hxx"

#ifndef _UTL_CONFIGMGR_HXX_
#include <unotools/configmgr.hxx>
#endif

#ifndef _UTL_CONFIGITEM_HXX_
#include <unotools/configitem.hxx>
#endif

#ifndef _TOOLS_DEBUG_HXX
#include <tools/debug.hxx>
#endif

#ifndef _COM_SUN_STAR_UNO_ANY_HXX_
#include <com/sun/star/uno/Any.hxx>
#endif

#ifndef _COM_SUN_STAR_UNO_SEQUENCE_HXX_
#include <com/sun/star/uno/Sequence.hxx>
#endif

//_________________________________________________________________________________________________________________
//  namespaces
//_________________________________________________________________________________________________________________

using namespace ::utl                   ;
using namespace ::rtl                   ;
using namespace ::osl                   ;
using namespace ::com::sun::star::uno   ;

//_________________________________________________________________________________________________________________
//  const
//_________________________________________________________________________________________________________________

#define ROOTNODE_WORKINGSET             OUString(RTL_CONSTASCII_USTRINGPARAM("Office.Common/WorkingSet"))
#define DEFAULT_WINDOWLIST              Sequence< OUString >()

#define PROPERTYNAME_WINDOWLIST         OUString(RTL_CONSTASCII_USTRINGPARAM("WindowList"       ))

#define PROPERTYHANDLE_WINDOWLIST       0

#define PROPERTYCOUNT                   1

//_________________________________________________________________________________________________________________
//  private declarations!
//_________________________________________________________________________________________________________________

class SvtWorkingSetOptions_Impl : public ConfigItem
{
    //-------------------------------------------------------------------------------------------------------------
    //  public methods
    //-------------------------------------------------------------------------------------------------------------

    public:

        //---------------------------------------------------------------------------------------------------------
        //  constructor / destructor
        //---------------------------------------------------------------------------------------------------------

         SvtWorkingSetOptions_Impl();
        ~SvtWorkingSetOptions_Impl();

        //---------------------------------------------------------------------------------------------------------
        //  overloaded methods of baseclass
        //---------------------------------------------------------------------------------------------------------

        /*-****************************************************************************************************//**
            @short      called for notify of configmanager
            @descr      These method is called from the ConfigManager before application ends or from the
                         PropertyChangeListener if the sub tree broadcasts changes. You must update your
                        internal values.

            @seealso    baseclass ConfigItem

            @param      "seqPropertyNames" is the list of properties which should be updated.
            @return     -

            @onerror    -
        *//*-*****************************************************************************************************/

        virtual void Notify( const Sequence< OUString >& seqPropertyNames );

        /*-****************************************************************************************************//**
            @short      write changes to configuration
            @descr      These method writes the changed values into the sub tree
                        and should always called in our destructor to guarantee consistency of config data.

            @seealso    baseclass ConfigItem

            @param      -
            @return     -

            @onerror    -
        *//*-*****************************************************************************************************/

        virtual void Commit();

        //---------------------------------------------------------------------------------------------------------
        //  public interface
        //---------------------------------------------------------------------------------------------------------

        /*-****************************************************************************************************//**
            @short      access method to get internal values
            @descr      These method give us a chance to regulate acces to ouer internal values.
                        It's not used in the moment - but it's possible for the feature!

            @seealso    -

            @param      -
            @return     -

            @onerror    -
        *//*-*****************************************************************************************************/

        Sequence< OUString >    GetWindowList(                                              ) const ;
        void                    SetWindowList( const Sequence< OUString >&  seqWindowList   )       ;

    //-------------------------------------------------------------------------------------------------------------
    //  private methods
    //-------------------------------------------------------------------------------------------------------------

    private:

        /*-****************************************************************************************************//**
            @short      return list of key names of ouer configuration management which represent oue module tree
            @descr      These methods return a static const list of key names. We need it to get needed values from our
                        configuration management.

            @seealso    -

            @param      -
            @return     A list of needed configuration keys is returned.

            @onerror    -
        *//*-*****************************************************************************************************/

        static Sequence< OUString > GetPropertyNames();

    //-------------------------------------------------------------------------------------------------------------
    //  private member
    //-------------------------------------------------------------------------------------------------------------

    private:

        Sequence< OUString >    m_seqWindowList     ;
};

//_________________________________________________________________________________________________________________
//  definitions
//_________________________________________________________________________________________________________________

//*****************************************************************************************************************
//  constructor
//*****************************************************************************************************************
SvtWorkingSetOptions_Impl::SvtWorkingSetOptions_Impl()
    // Init baseclasses first
    :   ConfigItem          ( ROOTNODE_WORKINGSET   )
    // Init member then.
    ,   m_seqWindowList     ( DEFAULT_WINDOWLIST    )
{
    // Use our static list of configuration keys to get his values.
    Sequence< OUString >    seqNames    = GetPropertyNames  (           );
    Sequence< Any >         seqValues   = GetProperties     ( seqNames  );

    // Safe impossible cases.
    // We need values from ALL configuration keys.
    // Follow assignment use order of values in relation to our list of key names!
    DBG_ASSERT( !(seqNames.getLength()!=seqValues.getLength()), "SvtWorkingSetOptions_Impl::SvtWorkingSetOptions_Impl()\nI miss some values of configuration keys!\n" );

    // Copy values from list in right order to ouer internal member.
    sal_Int32 nPropertyCount = seqValues.getLength();
    for( sal_Int32 nProperty=0; nProperty<nPropertyCount; ++nProperty )
    {
        // Safe impossible cases.
        // Check any for valid value.
        DBG_ASSERT( !(seqValues[nProperty].hasValue()==sal_False), "SvtWorkingSetOptions_Impl::SvtWorkingSetOptions_Impl()\nInvalid property value detected!\n" );
        switch( nProperty )
        {
            case PROPERTYHANDLE_WINDOWLIST      :   {
                                                        DBG_ASSERT(!(seqValues[nProperty].getValueTypeClass()!=TypeClass_SEQUENCE), "SvtWorkingSetOptions_Impl::SvtWorkingSetOptions_Impl()\nWho has changed the value type of \"Office.Common\\WorkingSet\\WindowList\"?" );
                                                        seqValues[nProperty] >>= m_seqWindowList;
                                                    }
                                                    break;
        }
    }

    // Enable notification mechanism of ouer baseclass.
    // We need it to get information about changes outside these class on ouer used configuration keys!
    EnableNotification( seqNames );
}

//*****************************************************************************************************************
//  destructor
//*****************************************************************************************************************
SvtWorkingSetOptions_Impl::~SvtWorkingSetOptions_Impl()
{
    // We must save our current values .. if user forget it!
    if( IsModified() == sal_True )
    {
        Commit();
    }
}

//*****************************************************************************************************************
//  public method
//*****************************************************************************************************************
void SvtWorkingSetOptions_Impl::Notify( const Sequence< OUString >& seqPropertyNames )
{
    // Use given list of updated properties to get his values from configuration directly!
    Sequence< Any > seqValues = GetProperties( seqPropertyNames );
    // Safe impossible cases.
    // We need values from ALL notified configuration keys.
    DBG_ASSERT( !(seqPropertyNames.getLength()!=seqValues.getLength()), "SvtWorkingSetOptions_Impl::Notify()\nI miss some values of configuration keys!\n" );
    // Step over list of property names and get right value from coreesponding value list to set it on internal members!
    sal_Int32 nCount = seqPropertyNames.getLength();
    for( sal_Int32 nProperty=0; nProperty<nCount; ++nProperty )
    {
        if( seqPropertyNames[nProperty] == PROPERTYNAME_WINDOWLIST )
        {
            DBG_ASSERT(!(seqValues[nProperty].getValueTypeClass()!=TypeClass_SEQUENCE), "SvtWorkingSetOptions_Impl::Notify()\nWho has changed the value type of \"Office.Common\\WorkingSet\\WindowList\"?" );
            seqValues[nProperty] >>= m_seqWindowList;
        }
        #if OSL_DEBUG_LEVEL > 1
        else DBG_ASSERT( sal_False, "SvtWorkingSetOptions_Impl::Notify()\nUnkown property detected ... I can't handle these!\n" );
        #endif
    }
}

//*****************************************************************************************************************
//  public method
//*****************************************************************************************************************
void SvtWorkingSetOptions_Impl::Commit()
{
    // Get names of supported properties, create a list for values and copy current values to it.
    Sequence< OUString >    seqNames    = GetPropertyNames  ();
    sal_Int32               nCount      = seqNames.getLength();
    Sequence< Any >         seqValues   ( nCount );
    for( sal_Int32 nProperty=0; nProperty<nCount; ++nProperty )
    {
        switch( nProperty )
        {
            case PROPERTYHANDLE_WINDOWLIST      :   {
                                                        seqValues[nProperty] <<= m_seqWindowList;
                                                    }
                                                    break;
        }
    }
    // Set properties in configuration.
    PutProperties( seqNames, seqValues );
}

//*****************************************************************************************************************
//  public method
//*****************************************************************************************************************
Sequence< OUString > SvtWorkingSetOptions_Impl::GetWindowList() const
{
    return m_seqWindowList;
}

//*****************************************************************************************************************
//  public method
//*****************************************************************************************************************
void SvtWorkingSetOptions_Impl::SetWindowList( const Sequence< OUString >& seqWindowList )
{
    m_seqWindowList = seqWindowList;
    SetModified();
}

//*****************************************************************************************************************
//  private method
//*****************************************************************************************************************
Sequence< OUString > SvtWorkingSetOptions_Impl::GetPropertyNames()
{
    // Build static list of configuration key names.
    static const OUString pProperties[] =
    {
        PROPERTYNAME_WINDOWLIST ,
    };
    // Initialize return sequence with these list ...
    static const Sequence< OUString > seqPropertyNames( pProperties, PROPERTYCOUNT );
    // ... and return it.
    return seqPropertyNames;
}

//*****************************************************************************************************************
//  initialize static member
//  DON'T DO IT IN YOUR HEADER!
//  see definition for further informations
//*****************************************************************************************************************
SvtWorkingSetOptions_Impl*  SvtWorkingSetOptions::m_pDataContainer  = NULL  ;
sal_Int32                   SvtWorkingSetOptions::m_nRefCount       = 0     ;

//*****************************************************************************************************************
//  constructor
//*****************************************************************************************************************
SvtWorkingSetOptions::SvtWorkingSetOptions()
{
    // Global access, must be guarded (multithreading!).
    MutexGuard aGuard( GetOwnStaticMutex() );
    // Increase ouer refcount ...
    ++m_nRefCount;
    // ... and initialize ouer data container only if it not already exist!
    if( m_pDataContainer == NULL )
    {
        m_pDataContainer = new SvtWorkingSetOptions_Impl;
    }
}

//*****************************************************************************************************************
//  destructor
//*****************************************************************************************************************
SvtWorkingSetOptions::~SvtWorkingSetOptions()
{
    // Global access, must be guarded (multithreading!)
    MutexGuard aGuard( GetOwnStaticMutex() );
    // Decrease ouer refcount.
    --m_nRefCount;
    // If last instance was deleted ...
    // we must destroy ouer static data container!
    if( m_nRefCount <= 0 )
    {
        delete m_pDataContainer;
        m_pDataContainer = NULL;
    }
}

//*****************************************************************************************************************
//  public method
//*****************************************************************************************************************
Sequence< OUString > SvtWorkingSetOptions::GetWindowList() const
{
    MutexGuard aGuard( GetOwnStaticMutex() );
    return m_pDataContainer->GetWindowList();
}

//*****************************************************************************************************************
//  public method
//*****************************************************************************************************************
void SvtWorkingSetOptions::SetWindowList( const Sequence< OUString >& seqWindowList )
{
    MutexGuard aGuard( GetOwnStaticMutex() );
    m_pDataContainer->SetWindowList( seqWindowList );
}

//*****************************************************************************************************************
//  private method
//*****************************************************************************************************************
Mutex& SvtWorkingSetOptions::GetOwnStaticMutex()
{
    // Initialize static mutex only for one time!
    static Mutex* pMutex = NULL;
    // If these method first called (Mutex not already exist!) ...
    if( pMutex == NULL )
    {
        // ... we must create a new one. Protect follow code with the global mutex -
        // It must be - we create a static variable!
        MutexGuard aGuard( Mutex::getGlobalMutex() );
        // We must check our pointer again - because it can be that another instance of ouer class will be fastr then these!
        if( pMutex == NULL )
        {
            // Create the new mutex and set it for return on static variable.
            static Mutex aMutex;
            pMutex = &aMutex;
        }
    }
    // Return new created or already existing mutex object.
    return *pMutex;
}
<|endoftext|>


<commit_before>/*
 *  Copyright 2008-2012 NVIDIA Corporation
 *
 *  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 <thrust/detail/config.h>
#include <thrust/system/detail/sequential/copy.h>
#include <thrust/detail/dispatch/is_trivial_copy.h>
#include <thrust/detail/type_traits.h>
#include <thrust/system/detail/sequential/general_copy.h>
#include <thrust/system/detail/sequential/trivial_copy.h>
#include <thrust/iterator/iterator_traits.h>
#include <thrust/detail/type_traits/pointer_traits.h>

namespace thrust
{
namespace system
{
namespace detail
{
namespace sequential
{
namespace copy_detail
{

// returns the raw pointer associated with a Pointer-like thing
template<typename Pointer>
__host__ __device__
  typename thrust::detail::pointer_traits<Pointer>::raw_pointer
    get(Pointer ptr)
{
  return thrust::detail::pointer_traits<Pointer>::get(ptr);
}

template<typename InputIterator,
         typename OutputIterator>
__host__ __device__
  OutputIterator copy(InputIterator first,
                      InputIterator last,
                      OutputIterator result,
                      thrust::detail::true_type)  // is_trivial_copy
{
  typedef typename thrust::iterator_difference<InputIterator>::type Size;

  const Size n = last - first;
  thrust::system::detail::sequential::trivial_copy_n(get(&*first), n, get(&*result));
  return result + n;
} // end copy()

__thrust_hd_warning_disable__
template<typename InputIterator,
         typename OutputIterator>
__host__ __device__
  OutputIterator copy(InputIterator first,
                      InputIterator last,
                      OutputIterator result,
                      thrust::detail::false_type)  // is_trivial_copy
{
  return thrust::system::detail::sequential::general_copy(first,last,result);
} // end copy()

template<typename InputIterator,
         typename Size,
         typename OutputIterator>
__host__ __device__
  OutputIterator copy_n(InputIterator first,
                        Size n,
                        OutputIterator result,
                        thrust::detail::true_type)  // is_trivial_copy
{
  thrust::system::detail::sequential::trivial_copy_n(get(&*first), n, get(&*result));
  return result + n;
} // end copy_n()

template<typename InputIterator,
         typename Size,
         typename OutputIterator>
__host__ __device__
  OutputIterator copy_n(InputIterator first,
                        Size n,
                        OutputIterator result,
                        thrust::detail::false_type)  // is_trivial_copy
{
  return thrust::system::detail::sequential::general_copy_n(first,n,result);
} // end copy_n()

} // end namespace copy_detail

__thrust_hd_warning_disable__
template<typename InputIterator,
         typename OutputIterator>
__host__ __device__
  OutputIterator copy(tag,
                      InputIterator first,
                      InputIterator last,
                      OutputIterator result)
{
  return thrust::system::detail::sequential::copy_detail::copy(first, last, result,
    typename thrust::detail::dispatch::is_trivial_copy<InputIterator,OutputIterator>::type());
} // end copy()

template<typename InputIterator,
         typename Size,
         typename OutputIterator>
__host__ __device__
  OutputIterator copy_n(tag,
                        InputIterator first,
                        Size n,
                        OutputIterator result)
{
  return thrust::system::detail::sequential::copy_detail::copy_n(first, n, result,
    typename thrust::detail::dispatch::is_trivial_copy<InputIterator,OutputIterator>::type());
} // end copy_n()

} // end namespace sequential
} // end namespace detail
} // end namespace system
} // end namespace thrust

<commit_msg>Suppress some warnings with __thrust_hd_warning_disable__.<commit_after>/*
 *  Copyright 2008-2012 NVIDIA Corporation
 *
 *  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 <thrust/detail/config.h>
#include <thrust/system/detail/sequential/copy.h>
#include <thrust/detail/dispatch/is_trivial_copy.h>
#include <thrust/detail/type_traits.h>
#include <thrust/system/detail/sequential/general_copy.h>
#include <thrust/system/detail/sequential/trivial_copy.h>
#include <thrust/iterator/iterator_traits.h>
#include <thrust/detail/type_traits/pointer_traits.h>

namespace thrust
{
namespace system
{
namespace detail
{
namespace sequential
{
namespace copy_detail
{

// returns the raw pointer associated with a Pointer-like thing
template<typename Pointer>
__host__ __device__
  typename thrust::detail::pointer_traits<Pointer>::raw_pointer
    get(Pointer ptr)
{
  return thrust::detail::pointer_traits<Pointer>::get(ptr);
}

__thrust_hd_warning_disable__
template<typename InputIterator,
         typename OutputIterator>
__host__ __device__
  OutputIterator copy(InputIterator first,
                      InputIterator last,
                      OutputIterator result,
                      thrust::detail::true_type)  // is_trivial_copy
{
  typedef typename thrust::iterator_difference<InputIterator>::type Size;

  const Size n = last - first;
  thrust::system::detail::sequential::trivial_copy_n(get(&*first), n, get(&*result));
  return result + n;
} // end copy()

__thrust_hd_warning_disable__
template<typename InputIterator,
         typename OutputIterator>
__host__ __device__
  OutputIterator copy(InputIterator first,
                      InputIterator last,
                      OutputIterator result,
                      thrust::detail::false_type)  // is_trivial_copy
{
  return thrust::system::detail::sequential::general_copy(first,last,result);
} // end copy()

__thrust_hd_warning_disable__
template<typename InputIterator,
         typename Size,
         typename OutputIterator>
__host__ __device__
  OutputIterator copy_n(InputIterator first,
                        Size n,
                        OutputIterator result,
                        thrust::detail::true_type)  // is_trivial_copy
{
  thrust::system::detail::sequential::trivial_copy_n(get(&*first), n, get(&*result));
  return result + n;
} // end copy_n()

template<typename InputIterator,
         typename Size,
         typename OutputIterator>
__host__ __device__
  OutputIterator copy_n(InputIterator first,
                        Size n,
                        OutputIterator result,
                        thrust::detail::false_type)  // is_trivial_copy
{
  return thrust::system::detail::sequential::general_copy_n(first,n,result);
} // end copy_n()

} // end namespace copy_detail

__thrust_hd_warning_disable__
template<typename InputIterator,
         typename OutputIterator>
__host__ __device__
  OutputIterator copy(tag,
                      InputIterator first,
                      InputIterator last,
                      OutputIterator result)
{
  return thrust::system::detail::sequential::copy_detail::copy(first, last, result,
    typename thrust::detail::dispatch::is_trivial_copy<InputIterator,OutputIterator>::type());
} // end copy()

template<typename InputIterator,
         typename Size,
         typename OutputIterator>
__host__ __device__
  OutputIterator copy_n(tag,
                        InputIterator first,
                        Size n,
                        OutputIterator result)
{
  return thrust::system::detail::sequential::copy_detail::copy_n(first, n, result,
    typename thrust::detail::dispatch::is_trivial_copy<InputIterator,OutputIterator>::type());
} // end copy_n()

} // end namespace sequential
} // end namespace detail
} // end namespace system
} // end namespace thrust

<|endoftext|>


<commit_before>/*
   This file is part of the clang-lazy static checker.

  Copyright (C) 2015 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com
  Author: Sérgio Martins <sergio.martins@kdab.com>

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

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

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

  You should have received a copy of the GNU General Public License along
  with this program; if not, write to the Free Software Foundation, Inc.,
  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.

  As a special exception, permission is given to link this program
  with any edition of Qt, and distribute the resulting executable,
  without including the source code for Qt in the source distribution.
*/

#include "nonpodstatic.h"
#include "Utils.h"
#include "StringUtils.h"
#include "checkmanager.h"

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

using namespace clang;
using namespace std;

static bool shouldIgnoreType(const std::string &name, const clang::CompilerInstance &ci)
{
    // Q_GLOBAL_STATIC and such
    static vector<string> blacklist = {"Holder", "AFUNC", "QLoggingCategory"};
    return find(blacklist.cbegin(), blacklist.cend(), name) != blacklist.cend();
}

NonPodStatic::NonPodStatic(const std::string &name, const clang::CompilerInstance &ci)
    : CheckBase(name, ci)
{
}

void NonPodStatic::VisitDecl(clang::Decl *decl)
{
    auto varDecl = dyn_cast<VarDecl>(decl);
    if (!varDecl || varDecl->isConstexpr() || varDecl->isExternallyVisible() || !varDecl->isFileVarDecl())
        return;

    StorageDuration sd = varDecl->getStorageDuration();
    if (sd != StorageDuration::SD_Static)
        return;

    QualType qt = varDecl->getType();
    const bool isTrivial = qt.isTrivialType(m_ci.getASTContext());
    if (isTrivial)
        return;

    const Type *t = qt.getTypePtrOrNull();
    if (!t || !t->getAsCXXRecordDecl() || t->getAsCXXRecordDecl()->isLiteral())
        return;

    const SourceLocation declStart = decl->getLocStart();

    auto macroName = Lexer::getImmediateMacroName(declStart, m_ci.getSourceManager(), m_ci.getLangOpts());
    if (stringStartsWith(macroName, "Q_CONSTRUCTOR_FUNCTION")) // Don't warn on these
        return;

    const string className = t->getAsCXXRecordDecl()->getName();
    if (!shouldIgnoreType(className, m_ci)) {
        std::string error = "non-POD static (" + className + ")";
        emitWarning(declStart, error.c_str());
    }
}

std::vector<string> NonPodStatic::filesToIgnore() const
{
    return {"main.cpp", "qrc_"};
}

REGISTER_CHECK_WITH_FLAGS("non-pod-global-static", NonPodStatic, CheckLevel1)
<commit_msg>non-pod-global-static: Don't warn for qdbusxml2cpp<commit_after>/*
   This file is part of the clang-lazy static checker.

  Copyright (C) 2015 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com
  Author: Sérgio Martins <sergio.martins@kdab.com>

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

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

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

  You should have received a copy of the GNU General Public License along
  with this program; if not, write to the Free Software Foundation, Inc.,
  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.

  As a special exception, permission is given to link this program
  with any edition of Qt, and distribute the resulting executable,
  without including the source code for Qt in the source distribution.
*/

#include "nonpodstatic.h"
#include "Utils.h"
#include "StringUtils.h"
#include "checkmanager.h"

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

using namespace clang;
using namespace std;

static bool shouldIgnoreType(const std::string &name, const clang::CompilerInstance &ci)
{
    // Q_GLOBAL_STATIC and such
    static vector<string> blacklist = {"Holder", "AFUNC", "QLoggingCategory"};
    return find(blacklist.cbegin(), blacklist.cend(), name) != blacklist.cend();
}

NonPodStatic::NonPodStatic(const std::string &name, const clang::CompilerInstance &ci)
    : CheckBase(name, ci)
{
}

void NonPodStatic::VisitDecl(clang::Decl *decl)
{
    auto varDecl = dyn_cast<VarDecl>(decl);
    if (!varDecl || varDecl->isConstexpr() || varDecl->isExternallyVisible() || !varDecl->isFileVarDecl())
        return;

    StorageDuration sd = varDecl->getStorageDuration();
    if (sd != StorageDuration::SD_Static)
        return;

    QualType qt = varDecl->getType();
    const bool isTrivial = qt.isTrivialType(m_ci.getASTContext());
    if (isTrivial)
        return;

    const Type *t = qt.getTypePtrOrNull();
    if (!t || !t->getAsCXXRecordDecl() || t->getAsCXXRecordDecl()->isLiteral())
        return;

    const SourceLocation declStart = decl->getLocStart();

    auto macroName = Lexer::getImmediateMacroName(declStart, m_ci.getSourceManager(), m_ci.getLangOpts());
    if (stringStartsWith(macroName, "Q_CONSTRUCTOR_FUNCTION")) // Don't warn on these
        return;

    const string className = t->getAsCXXRecordDecl()->getName();
    if (!shouldIgnoreType(className, m_ci)) {
        std::string error = "non-POD static (" + className + ")";
        emitWarning(declStart, error.c_str());
    }
}

std::vector<string> NonPodStatic::filesToIgnore() const
{
    return {"main.cpp", "qrc_", "qdbusxml2cpp"};
}

REGISTER_CHECK_WITH_FLAGS("non-pod-global-static", NonPodStatic, CheckLevel1)
<|endoftext|>