<commit_before>/*
 * The MIT License (MIT)
 *
 * Copyright (c) 2015 Microsoft Corporation
 *
 * -=- Robust Distributed System Nucleus (rDSN) -=-
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */

/*
 * Description:
 *     Unit-test for io_looper.
 *
 * Revision history:
 *     Nov., 2015, @xiaotz (Xiaotong Zhang), first version
 *     xxxx-xx-xx, author, fix bug about xxx
 */

#include <fstream>
#include <sstream>
#include <vector>
#include <string>
#include <queue>
#include <iostream>
#include <dsn/internal/aio_provider.h>
#include <gtest/gtest.h>
#include <dsn/service_api_cpp.h>
#include <dsn/internal/priority_queue.h>
#include "../core/group_address.h"
#include "../core/command_manager.h"
#include "../core/service_engine.h"
#include "test_utils.h"
#include "../tools/hpc/io_looper.h"

DEFINE_THREAD_POOL_CODE(THREAD_POOL_TEST_SERVER_2);
DEFINE_TASK_CODE_AIO(LPC_AIO_TEST_2, TASK_PRIORITY_COMMON, THREAD_POOL_TEST_SERVER_2);
DEFINE_TASK_CODE_AIO(LPC_AIO_TEST, TASK_PRIORITY_COMMON, THREAD_POOL_TEST_SERVER);

# ifdef __linux__

# include <sys/eventfd.h>
# include <libaio.h>

namespace dsn{
namespace test{
    class io_looper_for_test : public dsn::tools::io_looper
    {
    public:
        io_looper_for_test() : io_looper(){}
        virtual ~io_looper_for_test(){}
    public:
        virtual bool is_shared_timer_queue() override
        {
            if(io_looper::is_shared_timer_queue())
                return false;
            else
                return true;
        }
    };
}}

TEST(tools_hpc, io_looper)
{
    dsn::test::io_looper_for_test* io_looper = new dsn::test::io_looper_for_test();
    io_looper->start(::dsn::task::get_current_node(), 1);
    EXPECT_FALSE(io_looper->is_shared_timer_queue());

    int event_fd = eventfd(0, EFD_NONBLOCK);

    io_context_t ctx;
    memset(&ctx, 0, sizeof(ctx));
    auto ret = io_setup(128, &ctx); // 128 concurrent events
    EXPECT_TRUE(ret == 0);

    utils::notify_event* evt = new utils::notify_event();
    dsn::tools::io_loop_callback callback = [ctx, event_fd, evt](
            int native_error,
            uint32_t io_size,
            uintptr_t lolp_or_events
            )
    {
        int64_t finished_aio = 0;

        if (read(event_fd, &finished_aio, sizeof(finished_aio)) != sizeof(finished_aio))
        {
            if (errno == EAGAIN || errno == EWOULDBLOCK)
                return;
            dassert(false, "read number of aio completion from eventfd failed, err = %s",
                strerror(errno)
                );
        }
        EXPECT_EQ(1, finished_aio);

        struct io_event events[1];
        int ret;

        struct timespec tms;
        tms.tv_sec = 0;
        tms.tv_nsec = 0;

        ret = io_getevents(ctx, 1, 1, events, &tms);
        EXPECT_EQ(1, ret);
        EXPECT_EQ(0, static_cast<int>(events[0].res2));
        EXPECT_EQ(10, static_cast<int>(events[0].res));
        evt->notify();
    };

    auto err = io_looper->bind_io_handle((dsn_handle_t)(intptr_t)event_fd, &callback, EPOLLIN | EPOLLET);
    EXPECT_EQ(ERR_OK, err);

    std::remove("test_io_looper.tmp"); // delete file
    std::ofstream myfile;
    myfile.open ("test_io_looper.tmp");
    myfile << "abcdefghi$";
    myfile.close();
    int fd = ::open("test_io_looper.tmp", O_RDWR, 0666);
    char buffer[11];
    memset(buffer, 0, sizeof(buffer));

    struct iocb* cb = new iocb;
    memset(cb, 0, sizeof(iocb));
    io_prep_pread(cb, fd, buffer, 10, 0);
    io_set_eventfd(cb, event_fd);
    ret = io_submit(ctx, 1, &cb);
    EXPECT_EQ(1, ret);

    evt->wait();
    EXPECT_STREQ("abcdefghi$", buffer);

    err = io_looper->unbind_io_handle((dsn_handle_t)(intptr_t)event_fd, &callback);
    EXPECT_EQ(dsn::ERR_OK, err);

    delete io_looper;
    delete cb;
    delete evt;
}

void timer_callback(void* param)
{
    int* a = (int*)param;
    EXPECT_EQ(1, *a);
    *a = 2;
}

TEST(tools_hpc, io_looper_timer)
{
    if(dsn::service_engine::fast_instance().spec().semaphore_factory_name == "dsn::tools::sim_semaphore_provider")
        return;

    dsn::test::io_looper_for_test* io_looper = new dsn::test::io_looper_for_test();
    io_looper->start(::dsn::task::get_current_node(), 1);

    int* a = new int;
    *a = 1;
    dsn::task_c* t = new dsn::task_c(LPC_AIO_TEST, timer_callback, a);
    t->add_ref();

    t->set_delay(1000);
    t->add_ref();
    io_looper->add_timer(t);
    t->wait();

    EXPECT_EQ(2, *a);

    t->release_ref();

    io_looper->stop();
    delete io_looper;
}

# endif // ifdef __linux__
<commit_msg>fix build break due to task_c constructor change<commit_after>/*
 * The MIT License (MIT)
 *
 * Copyright (c) 2015 Microsoft Corporation
 *
 * -=- Robust Distributed System Nucleus (rDSN) -=-
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */

/*
 * Description:
 *     Unit-test for io_looper.
 *
 * Revision history:
 *     Nov., 2015, @xiaotz (Xiaotong Zhang), first version
 *     xxxx-xx-xx, author, fix bug about xxx
 */

#include <fstream>
#include <sstream>
#include <vector>
#include <string>
#include <queue>
#include <iostream>
#include <dsn/internal/aio_provider.h>
#include <gtest/gtest.h>
#include <dsn/service_api_cpp.h>
#include <dsn/internal/priority_queue.h>
#include "../core/group_address.h"
#include "../core/command_manager.h"
#include "../core/service_engine.h"
#include "test_utils.h"
#include "../tools/hpc/io_looper.h"

DEFINE_THREAD_POOL_CODE(THREAD_POOL_TEST_SERVER_2);
DEFINE_TASK_CODE_AIO(LPC_AIO_TEST_2, TASK_PRIORITY_COMMON, THREAD_POOL_TEST_SERVER_2);
DEFINE_TASK_CODE_AIO(LPC_AIO_TEST, TASK_PRIORITY_COMMON, THREAD_POOL_TEST_SERVER);

# ifdef __linux__

# include <sys/eventfd.h>
# include <libaio.h>

namespace dsn{
namespace test{
    class io_looper_for_test : public dsn::tools::io_looper
    {
    public:
        io_looper_for_test() : io_looper(){}
        virtual ~io_looper_for_test(){}
    public:
        virtual bool is_shared_timer_queue() override
        {
            if(io_looper::is_shared_timer_queue())
                return false;
            else
                return true;
        }
    };
}}

TEST(tools_hpc, io_looper)
{
    dsn::test::io_looper_for_test* io_looper = new dsn::test::io_looper_for_test();
    io_looper->start(::dsn::task::get_current_node(), 1);
    EXPECT_FALSE(io_looper->is_shared_timer_queue());

    int event_fd = eventfd(0, EFD_NONBLOCK);

    io_context_t ctx;
    memset(&ctx, 0, sizeof(ctx));
    auto ret = io_setup(128, &ctx); // 128 concurrent events
    EXPECT_TRUE(ret == 0);

    utils::notify_event* evt = new utils::notify_event();
    dsn::tools::io_loop_callback callback = [ctx, event_fd, evt](
            int native_error,
            uint32_t io_size,
            uintptr_t lolp_or_events
            )
    {
        int64_t finished_aio = 0;

        if (read(event_fd, &finished_aio, sizeof(finished_aio)) != sizeof(finished_aio))
        {
            if (errno == EAGAIN || errno == EWOULDBLOCK)
                return;
            dassert(false, "read number of aio completion from eventfd failed, err = %s",
                strerror(errno)
                );
        }
        EXPECT_EQ(1, finished_aio);

        struct io_event events[1];
        int ret;

        struct timespec tms;
        tms.tv_sec = 0;
        tms.tv_nsec = 0;

        ret = io_getevents(ctx, 1, 1, events, &tms);
        EXPECT_EQ(1, ret);
        EXPECT_EQ(0, static_cast<int>(events[0].res2));
        EXPECT_EQ(10, static_cast<int>(events[0].res));
        evt->notify();
    };

    auto err = io_looper->bind_io_handle((dsn_handle_t)(intptr_t)event_fd, &callback, EPOLLIN | EPOLLET);
    EXPECT_EQ(ERR_OK, err);

    std::remove("test_io_looper.tmp"); // delete file
    std::ofstream myfile;
    myfile.open ("test_io_looper.tmp");
    myfile << "abcdefghi$";
    myfile.close();
    int fd = ::open("test_io_looper.tmp", O_RDWR, 0666);
    char buffer[11];
    memset(buffer, 0, sizeof(buffer));

    struct iocb* cb = new iocb;
    memset(cb, 0, sizeof(iocb));
    io_prep_pread(cb, fd, buffer, 10, 0);
    io_set_eventfd(cb, event_fd);
    ret = io_submit(ctx, 1, &cb);
    EXPECT_EQ(1, ret);

    evt->wait();
    EXPECT_STREQ("abcdefghi$", buffer);

    err = io_looper->unbind_io_handle((dsn_handle_t)(intptr_t)event_fd, &callback);
    EXPECT_EQ(dsn::ERR_OK, err);

    delete io_looper;
    delete cb;
    delete evt;
}

void timer_callback(void* param)
{
    int* a = (int*)param;
    EXPECT_EQ(1, *a);
    *a = 2;
}

TEST(tools_hpc, io_looper_timer)
{
    if(dsn::service_engine::fast_instance().spec().semaphore_factory_name == "dsn::tools::sim_semaphore_provider")
        return;

    dsn::test::io_looper_for_test* io_looper = new dsn::test::io_looper_for_test();
    io_looper->start(::dsn::task::get_current_node(), 1);

    int* a = new int;
    *a = 1;
    dsn::task_c* t = new dsn::task_c(LPC_AIO_TEST, timer_callback, a, nullptr);
    t->add_ref();

    t->set_delay(1000);
    t->add_ref();
    io_looper->add_timer(t);
    t->wait();

    EXPECT_EQ(2, *a);

    t->release_ref();

    io_looper->stop();
    delete io_looper;
}

# endif // ifdef __linux__
<|endoftext|>


<commit_before><commit_msg>getOperandNum(): error if specified operand number is out of range.<commit_after><|endoftext|>


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

#ifndef SD_PAGE_CACHE_MANAGER_HXX
#define SD_PAGE_CACHE_MANAGER_HXX

#include <sal/types.h>
#include <boost/shared_ptr.hpp>
#include <memory>
#include <vector>

class Size;
class SdDrawDocument;
class SdrPage;

namespace sd { namespace slidesorter { namespace view {
class SlideSorterView;
class PageObjectViewObjectContact;
} } }

namespace sd { namespace slidesorter { namespace model {
class SlideSorterModel;
} } }

namespace sd { namespace slidesorter { namespace cache {

class BitmapCache;

/** Provide and manage the preview bitmap caches for all slide sorter
    instances.  There is one cache per active slide sorter plus a small
    number of caches that are no longer in use.  The later are kept to speed
    up the switching between views.
*/
class PageCacheManager
{
public:
    typedef BitmapCache Cache;
    typedef ::std::vector< ::std::pair<Size, ::boost::shared_ptr<BitmapCache> > > BestFittingPageCaches;

    /** Return the one instance of the PageCacheManager class.
    */
    static ::boost::shared_ptr<PageCacheManager> Instance (void);

    /** Look up the cache for the given model in which the previews have the
        specified size.  If no such cache exists, then one is created.  When
        a new BitmapCache is created its Recycle() method is called with a
        sorted list of existing caches from which the new one initialize its
        previews.
        @return
            The returned cache lives as long as somebody keeps a shared
            pointer and the ReleaseCache() method has not been called.
    */
    ::boost::shared_ptr<Cache> GetCache (
        SdDrawDocument* pDocument,
        const Size& rPreviewSize);

    /** Tell the cache manager to release its own reference to the specified
        cache.  After that the cache will live as long as the caller (and
        maybe others) holds its reference.
    */
    void ReleaseCache (const ::boost::shared_ptr<Cache>& rpCache);

    /** This is an information to the cache manager that the size of preview
        bitmaps in the specified cache has changed.

    */
    ::boost::shared_ptr<Cache> ChangeSize (
        const ::boost::shared_ptr<Cache>& rpCache,
        const Size& rOldPreviewSize,
        const Size& rNewPreviewSize);

    /** Invalidate the preview bitmap for one slide that belongs to the
        specified document.  The bitmaps for this slide in all caches are
        marked as out-of-date and will be re-created when they are requested
        the next time.
    */
    void InvalidatePreviewBitmap (
        SdDrawDocument* pDocument,
        const SdrPage* pPage);

    /** Invalidate all the caches that are currently in use and destroy
        those that are not.  This is used for example when the high contrast
        mode is turned on or off.
    */
    void InvalidateAllCaches (void);

private:
    /** Singleton instance of the cache manager.  Note that this is a weak
        pointer.  The (implementation class of) ViewShellBase holds a
        shared_ptr so that the cache manager has the same life time as the
        ViewShellBase.
    */
    static ::boost::weak_ptr<PageCacheManager> mpInstance;

    /// List of active caches.
    class PageCacheContainer;
    ::std::auto_ptr<PageCacheContainer> mpPageCaches;

    /// List of inactive, recently used caches.
    class RecentlyUsedPageCaches;
    ::std::auto_ptr<RecentlyUsedPageCaches> mpRecentlyUsedPageCaches;

    /** The maximal number of recently used caches that are kept alive after
        they have become inactive, i.e. after they are not used anymore by a
        slide sorter.
    */
    const sal_uInt32 mnMaximalRecentlyCacheCount;

    PageCacheManager (void);
    ~PageCacheManager (void);

    class Deleter;
    friend class Deleter;

    ::boost::shared_ptr<Cache> GetRecentlyUsedCache(
        SdDrawDocument* pDocument,
        const Size& rSize);

    /** Add the given cache to the list of recently used caches for the
        document.  There is one such list per document.  Each least has at
        most mnMaximalRecentlyCacheCount members.
    */
    void PutRecentlyUsedCache(
        SdDrawDocument* pDocument,
        const Size& rPreviewSize,
        const ::boost::shared_ptr<Cache>& rpCache);

    /** Return a sorted list of the available caches, both active caches and
        those recently used, for the given document.  The sort order is so
        that an exact match of the preview size is at the front.  Other
        caches follow with the largest size first.
    */
    BestFittingPageCaches GetBestFittingCaches (
        SdDrawDocument* pDocument,
        const Size& rPreviewSize);

    /** This method is used internally to initialize a newly created
        BitmapCache with already exisiting previews.
    */
    void Recycle (
        const ::boost::shared_ptr<Cache>& rpCache,
        SdDrawDocument* pDocument,
        const Size& rPreviewSize);
};

} } } // end of namespace ::sd::slidesorter::cache

#endif
<commit_msg>INTEGRATION: CWS presenterview (1.5.204); FILE MERGED 2008/02/26 12:26:50 af 1.5.204.1: #i18486# Dropped the use of templates for implementing cache classes.<commit_after>/*************************************************************************
 *
 *  $RCSfile: SlsPageCacheManager.hxx,v $
 *
 *  $Revision: 1.6 $
 *
 *  last change: $Author: kz $ $Date: 2008-04-03 14:32:45 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/

#ifndef SD_PAGE_CACHE_MANAGER_HXX
#define SD_PAGE_CACHE_MANAGER_HXX

#include <sal/types.h>
#include <com/sun/star/uno/XInterface.hpp>
#include <boost/shared_ptr.hpp>
#include <memory>
#include <vector>

class Size;
class SdDrawDocument;
class SdrPage;

namespace sd { namespace slidesorter { namespace view {
class SlideSorterView;
class PageObjectViewObjectContact;
} } }

namespace sd { namespace slidesorter { namespace model {
class SlideSorterModel;
} } }

namespace sd { namespace slidesorter { namespace cache {

namespace css = ::com::sun::star;

class BitmapCache;

/** Provide and manage the preview bitmap caches for all slide sorter
    instances.  There is one cache per active slide sorter plus a small
    number of caches that are no longer in use.  The later are kept to speed
    up the switching between views.
*/
class PageCacheManager
{
public:
    typedef BitmapCache Cache;
    typedef ::std::vector< ::std::pair<Size, ::boost::shared_ptr<BitmapCache> > > BestFittingPageCaches;
    typedef css::uno::Reference<css::uno::XInterface> DocumentKey;

    /** Return the one instance of the PageCacheManager class.
    */
    static ::boost::shared_ptr<PageCacheManager> Instance (void);

    /** Look up the cache for the given model in which the previews have the
        specified size.  If no such cache exists, then one is created.  When
        a new BitmapCache is created its Recycle() method is called with a
        sorted list of existing caches from which the new one initialize its
        previews.
        @return
            The returned cache lives as long as somebody keeps a shared
            pointer and the ReleaseCache() method has not been called.
    */
    ::boost::shared_ptr<Cache> GetCache (
        DocumentKey pDocument,
        const Size& rPreviewSize);

    /** Tell the cache manager to release its own reference to the specified
        cache.  After that the cache will live as long as the caller (and
        maybe others) holds its reference.
    */
    void ReleaseCache (const ::boost::shared_ptr<Cache>& rpCache);

    /** This is an information to the cache manager that the size of preview
        bitmaps in the specified cache has changed.

    */
    ::boost::shared_ptr<Cache> ChangeSize (
        const ::boost::shared_ptr<Cache>& rpCache,
        const Size& rOldPreviewSize,
        const Size& rNewPreviewSize);

    /** Invalidate the preview bitmap for one slide that belongs to the
        specified document.  The bitmaps for this slide in all caches are
        marked as out-of-date and will be re-created when they are requested
        the next time.
    */
    void InvalidatePreviewBitmap (
        DocumentKey pDocument,
        const SdrPage* pPage);

    /** Invalidate all the caches that are currently in use and destroy
        those that are not.  This is used for example when the high contrast
        mode is turned on or off.
    */
    void InvalidateAllCaches (void);

private:
    /** Singleton instance of the cache manager.  Note that this is a weak
        pointer.  The (implementation class of) ViewShellBase holds a
        shared_ptr so that the cache manager has the same life time as the
        ViewShellBase.
    */
    static ::boost::weak_ptr<PageCacheManager> mpInstance;

    /// List of active caches.
    class PageCacheContainer;
    ::std::auto_ptr<PageCacheContainer> mpPageCaches;

    /// List of inactive, recently used caches.
    class RecentlyUsedPageCaches;
    ::std::auto_ptr<RecentlyUsedPageCaches> mpRecentlyUsedPageCaches;

    /** The maximal number of recently used caches that are kept alive after
        they have become inactive, i.e. after they are not used anymore by a
        slide sorter.
    */
    const sal_uInt32 mnMaximalRecentlyCacheCount;

    PageCacheManager (void);
    ~PageCacheManager (void);

    class Deleter;
    friend class Deleter;

    ::boost::shared_ptr<Cache> GetRecentlyUsedCache(
        DocumentKey pDocument,
        const Size& rSize);

    /** Add the given cache to the list of recently used caches for the
        document.  There is one such list per document.  Each least has at
        most mnMaximalRecentlyCacheCount members.
    */
    void PutRecentlyUsedCache(
        DocumentKey pDocument,
        const Size& rPreviewSize,
        const ::boost::shared_ptr<Cache>& rpCache);

    /** Return a sorted list of the available caches, both active caches and
        those recently used, for the given document.  The sort order is so
        that an exact match of the preview size is at the front.  Other
        caches follow with the largest size first.
    */
    BestFittingPageCaches GetBestFittingCaches (
        DocumentKey pDocument,
        const Size& rPreviewSize);

    /** This method is used internally to initialize a newly created
        BitmapCache with already exisiting previews.
    */
    void Recycle (
        const ::boost::shared_ptr<Cache>& rpCache,
        DocumentKey pDocument,
        const Size& rPreviewSize);
};

} } } // end of namespace ::sd::slidesorter::cache

#endif
<|endoftext|>


<commit_before>/*
 * sections.cc
 *
 * Translate AtomSpace Sections to LG Exp's.
 *
 * Copyright (c) 2022 Linas Vepstas <linasvepstas@gmail.com>
 */
#ifdef HAVE_ATOMESE

#include <cstdlib>
#include <opencog/atomspace/AtomSpace.h>
#include <opencog/persist/api/StorageNode.h>
#include <opencog/persist/cog-storage/CogStorage.h>
#include <opencog/persist/file/FileStorage.h>
#include <opencog/persist/rocks/RocksStorage.h>
#include <opencog/persist/sexpr/Sexpr.h>
#include <opencog/nlp/types/atom_types.h>

#undef STRINGIFY

extern "C" {
#include "../link-includes.h"            // For Dictionary
#include "../dict-common/dict-common.h"  // for Dictionary_s
#include "../dict-common/dict-utils.h"   // for size_of_expression()
#include "../dict-ram/dict-ram.h"
#include "lookup-atomese.h"
};

#include "dict-atomese.h"
#include "local-as.h"

using namespace opencog;

// ===============================================================

static size_t count_sections(Local* local, const Handle& germ)
{
	// Are there any Sections in the local atomspace?
	size_t nsects = germ->getIncomingSetSizeByType(SECTION);
	if (0 < nsects or nullptr == local->stnp) return nsects;

	local->stnp->fetch_incoming_by_type(germ, SECTION);
	local->stnp->barrier();
	nsects = germ->getIncomingSetSizeByType(SECTION);

	return nsects;
}

/// Return true if the given word can be found in the dictionary,
/// else return false.
bool section_boolean_lookup(Dictionary dict, const char *s)
{
	Local* local = (Local*) (dict->as_server);
	Handle wrd = local->asp->add_node(WORD_NODE, s);

	// Are there any Sections for this word in the local atomspace?
	size_t nwrdsects = count_sections(local, wrd);

	// Does this word belong to any classes?
	size_t nclass = wrd->getIncomingSetSizeByType(MEMBER_LINK);
	if (0 == nclass and local->stnp)
	{
		local->stnp->fetch_incoming_by_type(wrd, MEMBER_LINK);
		local->stnp->barrier();
	}

	size_t nclssects = 0;
	for (const Handle& memb : wrd->getIncomingSetByType(MEMBER_LINK))
	{
		const Handle& wcl = memb->getOutgoingAtom(1);
		if (WORD_CLASS_NODE != wcl->get_type()) continue;
		nclssects += count_sections(local, wcl);
	}

	lgdebug(+D_SPEC+5,
		"section_boolean_lookup for >>%s<< found class=%lu nsects=%lu %lu\n",
		s, nclass, nwrdsects, nclssects);

	return 0 != (nwrdsects + nclssects);
}

// ===============================================================
/// Mapping LG connectors to AtomSpace connectors, and v.v.
///
/// An LG connector is a string of capital letters. It's generated on
/// the fly. It's associated with a `(Set (Word ..) (Word ...))`. There
/// are two lookup tasks. In this blob of code, when given the Set, we
/// need to find the matching LG string. For users of LG, we have the
/// inverse problem: given the LG string, what's the Set?
///
/// As of just right now, the best solution seems to be the traditional
/// one:
///
///    (Evaluation (Predicate "*-LG connector string-*")
///       (LgConnNode "ABC") (Set (Word ..) (Word ...)))
///
/// As of just right now, the above is held only in the local AtomSpace;
/// it is never written back to storage.

/// int to base-26 capital letters.
static std::string idtostr(uint64_t aid)
{
	std::string s;
	do
	{
		char c = (aid % 26) + 'A';
		s.push_back(c);
	}
	while (0 < (aid /= 26));

	return s;
}

/// Given a `(List (Word ...) (Word ...))` denoting a link, find the
/// corresponding LgConnNode, if it exists.
static Handle get_lg_conn(const Handle& wset, const Handle& key)
{
	for (const Handle& ev : wset->getIncomingSetByType(EVALUATION_LINK))
	{
		if (ev->getOutgoingAtom(0) == key)
			return ev->getOutgoingAtom(1);
	}
	return Handle::UNDEFINED;
}

/// Return a cached LG-compatible link string.
/// Assigns a new name, if one does not exist.
/// The Handle `lnk` is an ordered pair, left-right, two words/classes.
/// That is, `lnk` is `(List (Word ...) (Word ...))`
/// The link name is stored in an LgLinkNode, having the format
///
///     (Evaluation (Predicate "*-LG connector string-*")
///              (LgLinkNode "ASDF") (List (Word ...) (Word ...)))
///
std::string cached_linkname(Local* local, const Handle& lnk)
{
	// If we've already cached a connector string for this,
	// just return it.  Else build and cache a string.
	Handle lgc = get_lg_conn(lnk, local->linkp);
	if (lgc)
		return lgc->get_name();

	static uint64_t lid = 0;

	// idtostr(16562) is "ANY" and we want to reserve "ANY"
	if (16562 == lid) lid++;
	std::string slnk = idtostr(lid++);

	lgc = createNode(LG_LINK_NODE, slnk);
	local->asp->add_link(EVALUATION_LINK, local->linkp, lgc, lnk);
	return slnk;
}

/// Return a cached LG-compatible link string.
/// Assigns a new name, if one does not exist.
/// `germ` is the germ of the section, `ctcr` is one of the connectors.
static std::string get_linkname(Local* local, const Handle& germ,
                                const Handle& ctcr)
{
	// The connection target is the first Atom in the connector
	const Handle& tgt = ctcr->getOutgoingAtom(0);
	const Handle& dir = ctcr->getOutgoingAtom(1);
	const std::string& sdir = dir->get_name();

	// The link is the connection of both of these.
	if ('+' == sdir[0])
	{
		const Handle& lnk = local->asp->add_link(LIST_LINK, germ, tgt);
		return cached_linkname(local, lnk);
	}

	// Else direction is '-' and tgt comes before germ.
	const Handle& lnk = local->asp->add_link(LIST_LINK, tgt, germ);
	return cached_linkname(local, lnk);
}

// Debugging utility
void print_section(Dictionary dict, const Handle& sect)
{
	Local* local = (Local*) (dict->as_server);

	const Handle& germ = sect->getOutgoingAtom(0);
	printf("(%s: ", germ->get_name().c_str());

	const Handle& conseq = sect->getOutgoingAtom(1);
	for (const Handle& ctcr : conseq->getOutgoingSet())
	{
		// The connection target is the first Atom in the connector
		const Handle& tgt = ctcr->getOutgoingAtom(0);
		const Handle& dir = ctcr->getOutgoingAtom(1);
		const std::string& sdir = dir->get_name();
		printf("%s%c ", tgt->get_name().c_str(), sdir[0]);
	}
	printf(") == ");

	bool first = true;
	for (const Handle& ctcr : conseq->getOutgoingSet())
	{
		// Assign an upper-case name to the link.
		std::string slnk = get_linkname(local, germ, ctcr);

		const Handle& dir = ctcr->getOutgoingAtom(1);
		const std::string& sdir = dir->get_name();

		if (not first) printf("& ");
		first = false;
		printf("%s%c ", slnk.c_str(), sdir[0]);
	}
	printf("\n");
	fflush(stdout);
}

// ===============================================================

Exp* make_sect_exprs(Dictionary dict, const Handle& germ)
{
	Local* local = (Local*) (dict->as_server);
	Exp* orhead = nullptr;
	Exp* ortail = nullptr;

	// Create some optional links; these may be nullptr's.
	Exp* left_inside_any = make_any_exprs(dict, local->left_inside_any);
	Exp* right_inside_any = make_any_exprs(dict, local->right_inside_any);
	Exp* left_outside_any = make_any_exprs(dict, local->left_outside_any);
	Exp* right_outside_any = make_any_exprs(dict, local->right_outside_any);

	Exp* inside_any = right_inside_any;
	if (left_inside_any and right_inside_any)
		inside_any = make_and_node(dict->Exp_pool, left_inside_any, right_inside_any);
	else if (left_inside_any)
		inside_any = left_inside_any;

	// Loop over all Sections on the word.
	HandleSeq sects = germ->getIncomingSetByType(SECTION);
	for (const Handle& sect: sects)
	{
		// Apprently, some sections are missing costs. This is
		// most likey due to some data-processing bug, where the
		// MI's were not recomputed. For nw, we will silently
		// ignore this issue, and assign a default to them.
		double cost = local->cost_default;

		const ValuePtr& mivp = sect->getValue(local->miks);
		if (mivp)
		{
			// MI is the second entry in the vector.
			const FloatValuePtr& fmivp = FloatValueCast(mivp);
			double mi = fmivp->value()[local->cost_index];
			cost = (local->cost_scale * mi) + local->cost_offset;
		}

		// If the cost is too high, just skip this.
		if (local->cost_cutoff <= cost)
			continue;

		Exp* andhead = nullptr;
		Exp* andtail = nullptr;

		if (inside_any)
			andhead = make_and_node(dict->Exp_pool, inside_any, NULL);

#ifdef EXTRA_OPTIONAL_PAIRS
		Exp* optex = make_optional_node(dict->Exp_pool, epr);
		Exp* optey = make_optional_node(dict->Exp_pool, epr);
		// andhead = make_and_node(dict->Exp_pool, optex, NULL);
		andhead = make_and_node(dict->Exp_pool, optex, optey);
		andtail = optey;
#endif // EXTRA_OPTIONAL_PAIRS

		// The connector sequence the second Atom.
		// Loop over the connectors in the connector sequence.
		// The atomspace stores connectors in word-order, while LG
		// stores them as distance-from given word.  Thus, we have
		// to reverse the order when building the expression.
		const Handle& conseq = sect->getOutgoingAtom(1);
		for (const Handle& ctcr : conseq->getOutgoingSet())
		{
			// The direction is the second Atom in the connector
			const Handle& dir = ctcr->getOutgoingAtom(1);
			char cdir = dir->get_name().c_str()[0];

			/* Assign an upper-case name to the link. */
			const std::string& slnk = get_linkname(local, germ, ctcr);

			Exp* eee = make_connector_node(dict,
				dict->Exp_pool, slnk.c_str(), cdir, false);

			if ('+' == cdir)
				and_enchain_right(dict, andhead, andtail, eee);
			else if ('-' == cdir)
				and_enchain_left(dict, andhead, andtail, eee);
		}

		// Sanity-check the Section - this should never-ever happen!
		if (nullptr == andhead)
		{
			prt_error("Warning: Empty connector sequence for %s\n",
				sect->to_short_string().c_str());
			continue;
		}

		Exp* optel = make_optional_node(dict->Exp_pool, left_outside_any);
		and_enchain_left(dict, andhead, andtail, optel);
		Exp* opter = make_optional_node(dict->Exp_pool, right_outside_any);
		and_enchain_right(dict, andhead, andtail, opter);

		// Optional: shorten the expression,
		// if there's only one connector in it.
		if (nullptr == andhead->operand_first->operand_next)
		{
			Exp *tmp = andhead->operand_first;
			andhead->operand_first = NULL;
			// pool_free(dict->Exp_pool, andhead); // not needed!?
			andhead = tmp;
		}

		andhead->cost = cost;

		// Save the exp-section pairing in the AtomSpace.
		// XXX Why did we think this was needed ??
		// What were we going to do with it?
		// cache_disjunct_string(local, sect, andhead);

#if DEBUG
		print_section(dict, sect);
		const char* wrd = germ->get_name().c_str();
		printf("Word: '%s'  Exp: %s\n", wrd, lg_exp_stringify(andhead));
#endif

		// Add it to the linked list.
		or_enchain(dict, orhead, ortail, andhead);
	}

	if (nullptr == orhead) return ortail;
	return orhead;
}

#endif /* HAVE_ATOMESE */
<commit_msg>Bugfix chaining<commit_after>/*
 * sections.cc
 *
 * Translate AtomSpace Sections to LG Exp's.
 *
 * Copyright (c) 2022 Linas Vepstas <linasvepstas@gmail.com>
 */
#ifdef HAVE_ATOMESE

#include <cstdlib>
#include <opencog/atomspace/AtomSpace.h>
#include <opencog/persist/api/StorageNode.h>
#include <opencog/persist/cog-storage/CogStorage.h>
#include <opencog/persist/file/FileStorage.h>
#include <opencog/persist/rocks/RocksStorage.h>
#include <opencog/persist/sexpr/Sexpr.h>
#include <opencog/nlp/types/atom_types.h>

#undef STRINGIFY

extern "C" {
#include "../link-includes.h"            // For Dictionary
#include "../dict-common/dict-common.h"  // for Dictionary_s
#include "../dict-common/dict-utils.h"   // for size_of_expression()
#include "../dict-ram/dict-ram.h"
#include "lookup-atomese.h"
};

#include "dict-atomese.h"
#include "local-as.h"

using namespace opencog;

// ===============================================================

static size_t count_sections(Local* local, const Handle& germ)
{
	// Are there any Sections in the local atomspace?
	size_t nsects = germ->getIncomingSetSizeByType(SECTION);
	if (0 < nsects or nullptr == local->stnp) return nsects;

	local->stnp->fetch_incoming_by_type(germ, SECTION);
	local->stnp->barrier();
	nsects = germ->getIncomingSetSizeByType(SECTION);

	return nsects;
}

/// Return true if the given word can be found in the dictionary,
/// else return false.
bool section_boolean_lookup(Dictionary dict, const char *s)
{
	Local* local = (Local*) (dict->as_server);
	Handle wrd = local->asp->add_node(WORD_NODE, s);

	// Are there any Sections for this word in the local atomspace?
	size_t nwrdsects = count_sections(local, wrd);

	// Does this word belong to any classes?
	size_t nclass = wrd->getIncomingSetSizeByType(MEMBER_LINK);
	if (0 == nclass and local->stnp)
	{
		local->stnp->fetch_incoming_by_type(wrd, MEMBER_LINK);
		local->stnp->barrier();
	}

	size_t nclssects = 0;
	for (const Handle& memb : wrd->getIncomingSetByType(MEMBER_LINK))
	{
		const Handle& wcl = memb->getOutgoingAtom(1);
		if (WORD_CLASS_NODE != wcl->get_type()) continue;
		nclssects += count_sections(local, wcl);
	}

	lgdebug(+D_SPEC+5,
		"section_boolean_lookup for >>%s<< found class=%lu nsects=%lu %lu\n",
		s, nclass, nwrdsects, nclssects);

	return 0 != (nwrdsects + nclssects);
}

// ===============================================================
/// Mapping LG connectors to AtomSpace connectors, and v.v.
///
/// An LG connector is a string of capital letters. It's generated on
/// the fly. It's associated with a `(Set (Word ..) (Word ...))`. There
/// are two lookup tasks. In this blob of code, when given the Set, we
/// need to find the matching LG string. For users of LG, we have the
/// inverse problem: given the LG string, what's the Set?
///
/// As of just right now, the best solution seems to be the traditional
/// one:
///
///    (Evaluation (Predicate "*-LG connector string-*")
///       (LgConnNode "ABC") (Set (Word ..) (Word ...)))
///
/// As of just right now, the above is held only in the local AtomSpace;
/// it is never written back to storage.

/// int to base-26 capital letters.
static std::string idtostr(uint64_t aid)
{
	std::string s;
	do
	{
		char c = (aid % 26) + 'A';
		s.push_back(c);
	}
	while (0 < (aid /= 26));

	return s;
}

/// Given a `(List (Word ...) (Word ...))` denoting a link, find the
/// corresponding LgConnNode, if it exists.
static Handle get_lg_conn(const Handle& wset, const Handle& key)
{
	for (const Handle& ev : wset->getIncomingSetByType(EVALUATION_LINK))
	{
		if (ev->getOutgoingAtom(0) == key)
			return ev->getOutgoingAtom(1);
	}
	return Handle::UNDEFINED;
}

/// Return a cached LG-compatible link string.
/// Assigns a new name, if one does not exist.
/// The Handle `lnk` is an ordered pair, left-right, two words/classes.
/// That is, `lnk` is `(List (Word ...) (Word ...))`
/// The link name is stored in an LgLinkNode, having the format
///
///     (Evaluation (Predicate "*-LG connector string-*")
///              (LgLinkNode "ASDF") (List (Word ...) (Word ...)))
///
std::string cached_linkname(Local* local, const Handle& lnk)
{
	// If we've already cached a connector string for this,
	// just return it.  Else build and cache a string.
	Handle lgc = get_lg_conn(lnk, local->linkp);
	if (lgc)
		return lgc->get_name();

	static uint64_t lid = 0;

	// idtostr(16562) is "ANY" and we want to reserve "ANY"
	if (16562 == lid) lid++;
	std::string slnk = idtostr(lid++);

	lgc = createNode(LG_LINK_NODE, slnk);
	local->asp->add_link(EVALUATION_LINK, local->linkp, lgc, lnk);
	return slnk;
}

/// Return a cached LG-compatible link string.
/// Assigns a new name, if one does not exist.
/// `germ` is the germ of the section, `ctcr` is one of the connectors.
static std::string get_linkname(Local* local, const Handle& germ,
                                const Handle& ctcr)
{
	// The connection target is the first Atom in the connector
	const Handle& tgt = ctcr->getOutgoingAtom(0);
	const Handle& dir = ctcr->getOutgoingAtom(1);
	const std::string& sdir = dir->get_name();

	// The link is the connection of both of these.
	if ('+' == sdir[0])
	{
		const Handle& lnk = local->asp->add_link(LIST_LINK, germ, tgt);
		return cached_linkname(local, lnk);
	}

	// Else direction is '-' and tgt comes before germ.
	const Handle& lnk = local->asp->add_link(LIST_LINK, tgt, germ);
	return cached_linkname(local, lnk);
}

// Debugging utility
void print_section(Dictionary dict, const Handle& sect)
{
	Local* local = (Local*) (dict->as_server);

	const Handle& germ = sect->getOutgoingAtom(0);
	printf("(%s: ", germ->get_name().c_str());

	const Handle& conseq = sect->getOutgoingAtom(1);
	for (const Handle& ctcr : conseq->getOutgoingSet())
	{
		// The connection target is the first Atom in the connector
		const Handle& tgt = ctcr->getOutgoingAtom(0);
		const Handle& dir = ctcr->getOutgoingAtom(1);
		const std::string& sdir = dir->get_name();
		printf("%s%c ", tgt->get_name().c_str(), sdir[0]);
	}
	printf(") == ");

	bool first = true;
	for (const Handle& ctcr : conseq->getOutgoingSet())
	{
		// Assign an upper-case name to the link.
		std::string slnk = get_linkname(local, germ, ctcr);

		const Handle& dir = ctcr->getOutgoingAtom(1);
		const std::string& sdir = dir->get_name();

		if (not first) printf("& ");
		first = false;
		printf("%s%c ", slnk.c_str(), sdir[0]);
	}
	printf("\n");
	fflush(stdout);
}

// ===============================================================

Exp* make_sect_exprs(Dictionary dict, const Handle& germ)
{
	Local* local = (Local*) (dict->as_server);
	Exp* orhead = nullptr;
	Exp* ortail = nullptr;

	// Create some optional links; these may be nullptr's.
	Exp* left_inside_any = make_any_exprs(dict, local->left_inside_any);
	Exp* right_inside_any = make_any_exprs(dict, local->right_inside_any);
	Exp* left_outside_any = make_any_exprs(dict, local->left_outside_any);
	Exp* right_outside_any = make_any_exprs(dict, local->right_outside_any);

	Exp* inside_any = right_inside_any;
	if (left_inside_any and right_inside_any)
		inside_any = make_and_node(dict->Exp_pool, left_inside_any, right_inside_any);
	else if (left_inside_any)
		inside_any = left_inside_any;

	// Loop over all Sections on the word.
	HandleSeq sects = germ->getIncomingSetByType(SECTION);
	for (const Handle& sect: sects)
	{
		// Apprently, some sections are missing costs. This is
		// most likey due to some data-processing bug, where the
		// MI's were not recomputed. For nw, we will silently
		// ignore this issue, and assign a default to them.
		double cost = local->cost_default;

		const ValuePtr& mivp = sect->getValue(local->miks);
		if (mivp)
		{
			// MI is the second entry in the vector.
			const FloatValuePtr& fmivp = FloatValueCast(mivp);
			double mi = fmivp->value()[local->cost_index];
			cost = (local->cost_scale * mi) + local->cost_offset;
		}

		// If the cost is too high, just skip this.
		if (local->cost_cutoff <= cost)
			continue;

		Exp* andhead = nullptr;
		Exp* andtail = nullptr;

		if (inside_any)
			andhead = make_and_node(dict->Exp_pool, inside_any, NULL);

#ifdef EXTRA_OPTIONAL_PAIRS
		Exp* optex = make_optional_node(dict->Exp_pool, epr);
		Exp* optey = make_optional_node(dict->Exp_pool, epr);
		// andhead = make_and_node(dict->Exp_pool, optex, NULL);
		andhead = make_and_node(dict->Exp_pool, optex, optey);
		andtail = optey;
#endif // EXTRA_OPTIONAL_PAIRS

		// The connector sequence the second Atom.
		// Loop over the connectors in the connector sequence.
		// The atomspace stores connectors in word-order, while LG
		// stores them as distance-from given word.  Thus, we have
		// to reverse the order when building the expression.
		const Handle& conseq = sect->getOutgoingAtom(1);
		for (const Handle& ctcr : conseq->getOutgoingSet())
		{
			// The direction is the second Atom in the connector
			const Handle& dir = ctcr->getOutgoingAtom(1);
			char cdir = dir->get_name().c_str()[0];

			/* Assign an upper-case name to the link. */
			const std::string& slnk = get_linkname(local, germ, ctcr);

			Exp* eee = make_connector_node(dict,
				dict->Exp_pool, slnk.c_str(), cdir, false);

			if ('+' == cdir)
				and_enchain_right(dict, andhead, andtail, eee);
			else if ('-' == cdir)
				and_enchain_left(dict, andhead, andtail, eee);
		}

		// Sanity-check the Section - this should never-ever happen!
		if (nullptr == andhead)
		{
			prt_error("Warning: Empty connector sequence for %s\n",
				sect->to_short_string().c_str());
			continue;
		}

		if (left_outside_any)
		{
			Exp* optex = make_optional_node(dict->Exp_pool, left_outside_any);
			and_enchain_left(dict, andhead, andtail, optex);
		}
		if (right_outside_any)
		{
			Exp* optex = make_optional_node(dict->Exp_pool, right_outside_any);
			and_enchain_right(dict, andhead, andtail, optex);
		}

		// Optional: shorten the expression,
		// if there's only one connector in it.
		if (nullptr == andhead->operand_first->operand_next)
		{
			Exp *tmp = andhead->operand_first;
			andhead->operand_first = NULL;
			// pool_free(dict->Exp_pool, andhead); // not needed!?
			andhead = tmp;
		}

		andhead->cost = cost;

		// Save the exp-section pairing in the AtomSpace.
		// XXX Why did we think this was needed ??
		// What were we going to do with it?
		// cache_disjunct_string(local, sect, andhead);

#if DEBUG
		print_section(dict, sect);
		const char* wrd = germ->get_name().c_str();
		printf("Word: '%s'  Exp: %s\n", wrd, lg_exp_stringify(andhead));
#endif

		// Add it to the linked list.
		or_enchain(dict, orhead, ortail, andhead);
	}

	if (nullptr == orhead) return ortail;
	return orhead;
}

#endif /* HAVE_ATOMESE */
<|endoftext|>


<commit_before>// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
// This job type handles Chrome plugin network interception.  When a plugin
// wants to intercept a request, a job of this type is created.  The intercept
// job communicates with the plugin to retrieve the response headers and data.

#include "chrome/common/net/url_request_intercept_job.h"

#include "base/message_loop.h"
#include "base/string_util.h"
#include "chrome/common/chrome_plugin_lib.h"
#include "chrome/common/notification_service.h"
#include "net/base/io_buffer.h"
#include "net/base/net_errors.h"
#include "net/base/x509_certificate.h"
#include "net/http/http_response_headers.h"
#include "net/url_request/url_request.h"

using base::Time;
using base::TimeDelta;

//
// URLRequestInterceptJob
//

URLRequestInterceptJob::URLRequestInterceptJob(URLRequest* request,
                                               ChromePluginLib* plugin,
                                               ScopableCPRequest* cprequest)
    : URLRequestJob(request),
      cprequest_(cprequest),
      plugin_(plugin),
      read_buffer_(NULL) {
  cprequest_->data = this;  // see FromCPRequest().

  registrar_.Add(this, NotificationType::CHROME_PLUGIN_UNLOADED,
                 Source<ChromePluginLib>(plugin_));
}

URLRequestInterceptJob::~URLRequestInterceptJob() {
  if (plugin_) {
    plugin_->functions().request_funcs->end_request(cprequest_.get(),
                                                    CPERR_SUCCESS);
  }
}

void URLRequestInterceptJob::DetachPlugin() {
  registrar_.RemoveAll();
  plugin_ = NULL;
}

void URLRequestInterceptJob::Start() {
  // Start reading asynchronously so that all error reporting and data
  // callbacks happen as they would for network requests.
  MessageLoop::current()->PostTask(FROM_HERE, NewRunnableMethod(
      this, &URLRequestInterceptJob::StartAsync));
}

void URLRequestInterceptJob::Kill() {
  if (plugin_) {
    plugin_->functions().request_funcs->end_request(cprequest_.get(),
                                                    CPERR_CANCELLED);
    DetachPlugin();
  }
  URLRequestJob::Kill();
}

bool URLRequestInterceptJob::ReadRawData(net::IOBuffer* dest, int dest_size,
                                         int* bytes_read) {
  DCHECK_NE(dest_size, 0);
  DCHECK(bytes_read);

  if (!plugin_)
    return false;

  int rv = plugin_->functions().request_funcs->read(cprequest_.get(),
                                                    dest->data(), dest_size);
  if (rv >= 0) {
    *bytes_read = rv;
    return true;
  }

  if (rv == CPERR_IO_PENDING) {
    read_buffer_ = dest;
    read_buffer_size_ = dest_size;
    SetStatus(URLRequestStatus(URLRequestStatus::IO_PENDING, 0));
  } else {
    // TODO(mpcomplete): better error code
    NotifyDone(URLRequestStatus(URLRequestStatus::FAILED, net::ERR_FAILED));
  }

  return false;
}

bool URLRequestInterceptJob::GetMimeType(std::string* mime_type) const {
  return request_->response_headers()->GetMimeType(mime_type);
}

bool URLRequestInterceptJob::GetCharset(std::string* charset) {
  return request_->response_headers()->GetCharset(charset);
}

bool URLRequestInterceptJob::GetContentEncodings(
    std::vector<Filter::FilterType>* encoding_types) {
  DCHECK(encoding_types->empty());
  if (!request_->response_headers())
    return false;

  std::string encoding_type;
  void* iter = NULL;
  while (request_->response_headers()->EnumerateHeader(
      &iter, "Content-Encoding", &encoding_type)) {
    encoding_types->push_back(Filter::ConvertEncodingToType(encoding_type));
  }

  // Even if encoding types are empty, there is a chance that we need to add
  // some decoding, as some proxies strip encoding completely. In such cases,
  // we may need to add (for example) SDCH filtering (when the context suggests
  // it is appropriate).
  Filter::FixupEncodingTypes(*this, encoding_types);
  return !encoding_types->empty();
}

void URLRequestInterceptJob::GetResponseInfo(net::HttpResponseInfo* info) {
  if (!plugin_)
    return;

  std::string raw_headers;
  int size = plugin_->functions().request_funcs->get_response_info(
      cprequest_.get(), CPRESPONSEINFO_HTTP_RAW_HEADERS, NULL, 0);
  int rv = size < 0 ? size :
      plugin_->functions().request_funcs->get_response_info(
          cprequest_.get(), CPRESPONSEINFO_HTTP_RAW_HEADERS,
          WriteInto(&raw_headers, size+1), size);
  if (rv != CPERR_SUCCESS) {
    // TODO(mpcomplete): what should we do here?
    raw_headers = "HTTP/1.1 404 Not Found" + '\0';
  }

  info->headers = new net::HttpResponseHeaders(raw_headers);

  if (request_->url().SchemeIsSecure()) {
    // Make up a fake certificate for intercepted data since we don't have
    // access to the real SSL info.
    // TODO(mpcomplete): we should probably have the interception API transmit
    // the SSL info, but the only consumer of this API (Gears) doesn't keep that
    // around. We should change that.
    const char* kCertIssuer = "Chrome Internal";
    const int kLifetimeDays = 100;

    DLOG(WARNING) << "Issuing a fake SSL certificate for interception of URL "
        << request_->url();

    info->ssl_info.cert =
        new net::X509Certificate(request_->url().GetWithEmptyPath().spec(),
                                 kCertIssuer,
                                 Time::Now(),
                                 Time::Now() +
                                     TimeDelta::FromDays(kLifetimeDays));
    info->ssl_info.cert_status = 0;
    info->ssl_info.security_bits = 0;
  }
}

int URLRequestInterceptJob::GetResponseCode() const {
  if (!plugin_)
    return -1;

  int status = 200;
  plugin_->functions().request_funcs->get_response_info(
      cprequest_.get(), CPRESPONSEINFO_HTTP_STATUS, &status, sizeof(status));

  return status;
}

bool URLRequestInterceptJob::IsRedirectResponse(GURL* location,
                                                int* http_status_code) {
  if (!request_->response_headers())
    return false;

  std::string value;
  if (!request_->response_headers()->IsRedirect(&value))
    return false;

  *location = request_->url().Resolve(value);
  *http_status_code = request_->response_headers()->response_code();
  return true;
}

void URLRequestInterceptJob::StartAsync() {
  // We may have been orphaned...
  if (!request_ || !plugin_)
    return;

  int rv = plugin_->functions().request_funcs->start_request(cprequest_.get());
  if (rv != CPERR_IO_PENDING)
    OnStartCompleted(rv);
}

void URLRequestInterceptJob::OnStartCompleted(int result) {
  if (result != CPERR_SUCCESS) {
    NotifyDone(URLRequestStatus(URLRequestStatus::FAILED,
                                net::ERR_CONNECTION_FAILED));
    return;
  }

  NotifyHeadersComplete();
}

void URLRequestInterceptJob::OnReadCompleted(int bytes_read) {
  if (bytes_read < 0) {
    NotifyDone(URLRequestStatus(URLRequestStatus::FAILED, net::ERR_FAILED));
    return;
  }

  SetStatus(URLRequestStatus());  // clear the async flag
  NotifyReadComplete(bytes_read);
}

void URLRequestInterceptJob::Observe(NotificationType type,
                                     const NotificationSource& source,
                                     const NotificationDetails& details) {
  DCHECK(type == NotificationType::CHROME_PLUGIN_UNLOADED);
  DCHECK(plugin_ == Source<ChromePluginLib>(source).ptr());
  DetachPlugin();
}
<commit_msg>Fix unintentional pointer arithmetic.<commit_after>// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
// This job type handles Chrome plugin network interception.  When a plugin
// wants to intercept a request, a job of this type is created.  The intercept
// job communicates with the plugin to retrieve the response headers and data.

#include "chrome/common/net/url_request_intercept_job.h"

#include "base/message_loop.h"
#include "base/string_util.h"
#include "chrome/common/chrome_plugin_lib.h"
#include "chrome/common/notification_service.h"
#include "net/base/io_buffer.h"
#include "net/base/net_errors.h"
#include "net/base/x509_certificate.h"
#include "net/http/http_response_headers.h"
#include "net/url_request/url_request.h"

using base::Time;
using base::TimeDelta;

//
// URLRequestInterceptJob
//

URLRequestInterceptJob::URLRequestInterceptJob(URLRequest* request,
                                               ChromePluginLib* plugin,
                                               ScopableCPRequest* cprequest)
    : URLRequestJob(request),
      cprequest_(cprequest),
      plugin_(plugin),
      read_buffer_(NULL) {
  cprequest_->data = this;  // see FromCPRequest().

  registrar_.Add(this, NotificationType::CHROME_PLUGIN_UNLOADED,
                 Source<ChromePluginLib>(plugin_));
}

URLRequestInterceptJob::~URLRequestInterceptJob() {
  if (plugin_) {
    plugin_->functions().request_funcs->end_request(cprequest_.get(),
                                                    CPERR_SUCCESS);
  }
}

void URLRequestInterceptJob::DetachPlugin() {
  registrar_.RemoveAll();
  plugin_ = NULL;
}

void URLRequestInterceptJob::Start() {
  // Start reading asynchronously so that all error reporting and data
  // callbacks happen as they would for network requests.
  MessageLoop::current()->PostTask(FROM_HERE, NewRunnableMethod(
      this, &URLRequestInterceptJob::StartAsync));
}

void URLRequestInterceptJob::Kill() {
  if (plugin_) {
    plugin_->functions().request_funcs->end_request(cprequest_.get(),
                                                    CPERR_CANCELLED);
    DetachPlugin();
  }
  URLRequestJob::Kill();
}

bool URLRequestInterceptJob::ReadRawData(net::IOBuffer* dest, int dest_size,
                                         int* bytes_read) {
  DCHECK_NE(dest_size, 0);
  DCHECK(bytes_read);

  if (!plugin_)
    return false;

  int rv = plugin_->functions().request_funcs->read(cprequest_.get(),
                                                    dest->data(), dest_size);
  if (rv >= 0) {
    *bytes_read = rv;
    return true;
  }

  if (rv == CPERR_IO_PENDING) {
    read_buffer_ = dest;
    read_buffer_size_ = dest_size;
    SetStatus(URLRequestStatus(URLRequestStatus::IO_PENDING, 0));
  } else {
    // TODO(mpcomplete): better error code
    NotifyDone(URLRequestStatus(URLRequestStatus::FAILED, net::ERR_FAILED));
  }

  return false;
}

bool URLRequestInterceptJob::GetMimeType(std::string* mime_type) const {
  return request_->response_headers()->GetMimeType(mime_type);
}

bool URLRequestInterceptJob::GetCharset(std::string* charset) {
  return request_->response_headers()->GetCharset(charset);
}

bool URLRequestInterceptJob::GetContentEncodings(
    std::vector<Filter::FilterType>* encoding_types) {
  DCHECK(encoding_types->empty());
  if (!request_->response_headers())
    return false;

  std::string encoding_type;
  void* iter = NULL;
  while (request_->response_headers()->EnumerateHeader(
      &iter, "Content-Encoding", &encoding_type)) {
    encoding_types->push_back(Filter::ConvertEncodingToType(encoding_type));
  }

  // Even if encoding types are empty, there is a chance that we need to add
  // some decoding, as some proxies strip encoding completely. In such cases,
  // we may need to add (for example) SDCH filtering (when the context suggests
  // it is appropriate).
  Filter::FixupEncodingTypes(*this, encoding_types);
  return !encoding_types->empty();
}

void URLRequestInterceptJob::GetResponseInfo(net::HttpResponseInfo* info) {
  if (!plugin_)
    return;

  std::string raw_headers;
  int size = plugin_->functions().request_funcs->get_response_info(
      cprequest_.get(), CPRESPONSEINFO_HTTP_RAW_HEADERS, NULL, 0);
  int rv = size < 0 ? size :
      plugin_->functions().request_funcs->get_response_info(
          cprequest_.get(), CPRESPONSEINFO_HTTP_RAW_HEADERS,
          WriteInto(&raw_headers, size+1), size);
  if (rv != CPERR_SUCCESS) {
    // TODO(mpcomplete): what should we do here?
    raw_headers = "HTTP/1.1 404 Not Found";
    raw_headers.push_back('\0');
  }

  info->headers = new net::HttpResponseHeaders(raw_headers);

  if (request_->url().SchemeIsSecure()) {
    // Make up a fake certificate for intercepted data since we don't have
    // access to the real SSL info.
    // TODO(mpcomplete): we should probably have the interception API transmit
    // the SSL info, but the only consumer of this API (Gears) doesn't keep that
    // around. We should change that.
    const char* kCertIssuer = "Chrome Internal";
    const int kLifetimeDays = 100;

    DLOG(WARNING) << "Issuing a fake SSL certificate for interception of URL "
        << request_->url();

    info->ssl_info.cert =
        new net::X509Certificate(request_->url().GetWithEmptyPath().spec(),
                                 kCertIssuer,
                                 Time::Now(),
                                 Time::Now() +
                                     TimeDelta::FromDays(kLifetimeDays));
    info->ssl_info.cert_status = 0;
    info->ssl_info.security_bits = 0;
  }
}

int URLRequestInterceptJob::GetResponseCode() const {
  if (!plugin_)
    return -1;

  int status = 200;
  plugin_->functions().request_funcs->get_response_info(
      cprequest_.get(), CPRESPONSEINFO_HTTP_STATUS, &status, sizeof(status));

  return status;
}

bool URLRequestInterceptJob::IsRedirectResponse(GURL* location,
                                                int* http_status_code) {
  if (!request_->response_headers())
    return false;

  std::string value;
  if (!request_->response_headers()->IsRedirect(&value))
    return false;

  *location = request_->url().Resolve(value);
  *http_status_code = request_->response_headers()->response_code();
  return true;
}

void URLRequestInterceptJob::StartAsync() {
  // We may have been orphaned...
  if (!request_ || !plugin_)
    return;

  int rv = plugin_->functions().request_funcs->start_request(cprequest_.get());
  if (rv != CPERR_IO_PENDING)
    OnStartCompleted(rv);
}

void URLRequestInterceptJob::OnStartCompleted(int result) {
  if (result != CPERR_SUCCESS) {
    NotifyDone(URLRequestStatus(URLRequestStatus::FAILED,
                                net::ERR_CONNECTION_FAILED));
    return;
  }

  NotifyHeadersComplete();
}

void URLRequestInterceptJob::OnReadCompleted(int bytes_read) {
  if (bytes_read < 0) {
    NotifyDone(URLRequestStatus(URLRequestStatus::FAILED, net::ERR_FAILED));
    return;
  }

  SetStatus(URLRequestStatus());  // clear the async flag
  NotifyReadComplete(bytes_read);
}

void URLRequestInterceptJob::Observe(NotificationType type,
                                     const NotificationSource& source,
                                     const NotificationDetails& details) {
  DCHECK(type == NotificationType::CHROME_PLUGIN_UNLOADED);
  DCHECK(plugin_ == Source<ChromePluginLib>(source).ptr());
  DetachPlugin();
}
<|endoftext|>


<commit_before>#include <cppunit/Exception.h>
#include <cppunit/extensions/TypeInfoHelper.h>
#include "DefaultProtector.h"

CPPUNIT_NS_BEGIN

bool
DefaultProtector::protect( const Functor &functor,
                           const ProtectorContext &context )
{
  try
  {
    return functor();
  }
  catch ( Exception &failure )
  {
    reportFailure( context, failure );
  }
  catch ( std::exception &e )
  {
    std::string shortDescription( "uncaught exception of type " );
#if CPPUNIT_USE_TYPEINFO_NAME
    shortDescription += TypeInfoHelper::getClassName( typeid(e) );
#else
    shortDescription += "std::exception (or derived)."
#endif
    Message message( shortDescription, e.what() );
    reportError( context, message );
  }
  catch ( ... )
  {
    reportError( context,
                 Message( "uncaught exception of unknown type") );
  }

  return false;
}

CPPUNIT_NS_END
<commit_msg>Missing semicolon when CPPUNIT_USE_TYPEINFO_NAME not used<commit_after>#include <cppunit/Exception.h>
#include <cppunit/extensions/TypeInfoHelper.h>
#include "DefaultProtector.h"

CPPUNIT_NS_BEGIN

bool
DefaultProtector::protect( const Functor &functor,
                           const ProtectorContext &context )
{
  try
  {
    return functor();
  }
  catch ( Exception &failure )
  {
    reportFailure( context, failure );
  }
  catch ( std::exception &e )
  {
    std::string shortDescription( "uncaught exception of type " );
#if CPPUNIT_USE_TYPEINFO_NAME
    shortDescription += TypeInfoHelper::getClassName( typeid(e) );
#else
    shortDescription += "std::exception (or derived).";
#endif
    Message message( shortDescription, e.what() );
    reportError( context, message );
  }
  catch ( ... )
  {
    reportError( context,
                 Message( "uncaught exception of unknown type") );
  }

  return false;
}

CPPUNIT_NS_END
<|endoftext|>


<commit_before>/****************************************************************************
**
** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the Qt Mobility Components.
**
** $QT_BEGIN_LICENSE:LGPL$
** No Commercial Usage
** This file contains pre-release code and may not be distributed.
** You may use this file in accordance with the terms and conditions
** contained in the Technology Preview License Agreement accompanying
** this package.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights.  These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
**
**
**
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/

#include "contacteditor.h"

#include <QtGui>

ContactEditor::ContactEditor(QWidget *parent)
        :QWidget(parent)
{
    m_manager = 0;
    m_contactId = QContactLocalId(0);

#ifdef Q_OS_SYMBIAN
    // In symbian "save" and "cancel" buttons are softkeys.
    m_saveBtn = new QAction("Save", this);
    m_saveBtn->setSoftKeyRole(QAction::PositiveSoftKey);
    addAction(m_saveBtn);
    connect(m_saveBtn, SIGNAL(triggered(bool)), this, SLOT(saveClicked()));
    m_cancelBtn = new QAction("Cancel", this);
    m_cancelBtn->setSoftKeyRole(QAction::NegativeSoftKey);
    addAction(m_cancelBtn);
    connect(m_cancelBtn, SIGNAL(triggered(bool)), this, SLOT(cancelClicked()));
#else
    m_saveBtn = new QPushButton("Save", this);
    connect(m_saveBtn, SIGNAL(clicked()), this, SLOT(saveClicked()));
    m_cancelBtn = new QPushButton("Cancel", this);
    connect(m_cancelBtn, SIGNAL(clicked()), this, SLOT(cancelClicked()));
#endif

    m_nameEdit = new QLineEdit(this);
    m_phoneEdit = new QLineEdit(this);
    m_emailEdit = new QLineEdit(this);
    m_addrEdit = new QLineEdit(this);
    m_avatarBtn = new QPushButton("Add image", this);
    m_avatarBtn->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
    connect(m_avatarBtn, SIGNAL(clicked()), this, SLOT(avatarClicked()));

    QFormLayout *detailsLayout = new QFormLayout;
    detailsLayout->addRow(new QLabel("Name", this));
    detailsLayout->addRow(m_nameEdit);
    detailsLayout->addRow(new QLabel("Phone", this));
    detailsLayout->addRow(m_phoneEdit);
    detailsLayout->addRow(new QLabel("Email", this));
    detailsLayout->addRow(m_emailEdit);
    detailsLayout->addRow(new QLabel("Address", this));
    detailsLayout->addRow(m_addrEdit);
    detailsLayout->addRow(new QLabel("Avatar", this));
    detailsLayout->addRow(m_avatarBtn);
    detailsLayout->setFieldGrowthPolicy(QFormLayout::ExpandingFieldsGrow);
    detailsLayout->setSizeConstraint(QLayout::SetMinAndMaxSize);

    QScrollArea *detailsScrollArea = new QScrollArea(this);
    detailsScrollArea->setWidgetResizable(true);
    QWidget *detailsContainer = new QWidget(detailsScrollArea);
    detailsContainer->setLayout(detailsLayout);
    detailsScrollArea->setWidget(detailsContainer);

#ifndef Q_OS_SYMBIAN
    QHBoxLayout *btnLayout = new QHBoxLayout;
    btnLayout->addWidget(m_saveBtn);
    btnLayout->addWidget(m_cancelBtn);
#endif

    QVBoxLayout *editLayout = new QVBoxLayout;
    editLayout->addWidget(detailsScrollArea);
#ifndef Q_OS_SYMBIAN
    editLayout->addLayout(btnLayout);
#endif

    setLayout(editLayout);
}

ContactEditor::~ContactEditor()
{
}

void ContactEditor::setCurrentContact(QContactManager* manager, QContactLocalId currentId)
{
    m_manager = manager;
    m_contactId = currentId;
    m_newAvatarPath = QString();

    // Clear UI
    m_nameEdit->setText("");
    m_phoneEdit->setText("");
    m_emailEdit->setText("");
    m_addrEdit->setText("");
    m_avatarBtn->setText("Add image");
    m_avatarBtn->setIcon(QIcon());

    if (manager == 0) {
        m_saveBtn->setEnabled(false);
        return;
    }

    // enable the UI.
    m_saveBtn->setEnabled(true);

    // otherwise, build from the contact details.
    QContact curr;
    if (m_contactId != QContactLocalId(0))
        curr = manager->contact(m_contactId);

    // Disable fields & buttons according to what the backend supports
    QMap<QString, QContactDetailDefinition> defs = m_manager->detailDefinitions(QContactType::TypeContact);

    // name
    //QContactName nm = curr.detail(QContactName::DefinitionName);
    if (m_contactId != QContactLocalId(0))
        m_nameEdit->setText(manager->synthesizedDisplayLabel(curr));

    // phonenumber
    QContactPhoneNumber phn = curr.detail(QContactPhoneNumber::DefinitionName);
    m_phoneEdit->setText(phn.value(QContactPhoneNumber::FieldNumber));

    // email
    if (defs.contains(QContactEmailAddress::DefinitionName)) {
        QContactEmailAddress em = curr.detail(QContactEmailAddress::DefinitionName);
        m_emailEdit->setText(em.value(QContactEmailAddress::FieldEmailAddress));
        m_emailEdit->setReadOnly(false);
    } else {
        m_emailEdit->setText("<not supported>");
        m_emailEdit->setReadOnly(true);
    }

    // address
    if (defs.contains(QContactAddress::DefinitionName)) {
        QContactAddress adr = curr.detail(QContactAddress::DefinitionName);
        m_addrEdit->setText(adr.value(QContactAddress::FieldStreet)); // ugly hack.
        m_addrEdit->setReadOnly(false);
    } else {
        m_addrEdit->setText("<not supported>");
        m_addrEdit->setReadOnly(true);
    }

    // avatar button
    if (defs.contains(QContactAvatar::DefinitionName)) {
        QContactAvatar av = curr.detail(QContactAvatar::DefinitionName);
        QContactThumbnail thumb = curr.detail(QContactThumbnail::DefinitionName);
        m_avatarBtn->setText(QString());
        m_avatarBtn->setIcon(QIcon());
        if (thumb.thumbnail().isNull()) {
            if (av.imageUrl().isEmpty()) {
                m_avatarBtn->setText("Add image");
            } else {
                m_avatarBtn->setIcon(QIcon(QPixmap(av.imageUrl().toLocalFile())));
                m_thumbnail = QImage(av.imageUrl().toLocalFile());
            }
        } else {
            m_newAvatarPath = av.imageUrl().toLocalFile();
            m_thumbnail = thumb.thumbnail();
            m_avatarBtn->setIcon(QIcon(QPixmap::fromImage(thumb.thumbnail())));
        }
        m_avatarBtn->setDisabled(false);
    } else {
        m_avatarBtn->setIcon(QIcon());
        m_avatarBtn->setText("<not supported>");
        m_avatarBtn->setDisabled(true);
    }
}

QString ContactEditor::nameField()
{
    // return the field which the name data should be saved in.
    if (!m_manager)
        return QString();

    QMap<QString, QContactDetailDefinition> defs = m_manager->detailDefinitions(QContactType::TypeContact);
    QContactDetailDefinition nameDef = defs.value(QContactName::DefinitionName);
    if (nameDef.fields().keys().contains(QContactName::FieldCustomLabel)) {
        return QString(QLatin1String(QContactName::FieldCustomLabel));
    } else if (nameDef.fields().keys().contains(QContactName::FieldFirstName)) {
        return QString(QLatin1String(QContactName::FieldFirstName));
    } else {
        return QString();
    }
}

void ContactEditor::avatarClicked()
{
    // put up a file dialog, and update the new avatar path.
    QString fileName = QFileDialog::getOpenFileName(this,
       tr("Select Avatar Image"), ".", tr("Image Files (*.png *.jpg *.bmp)"));

    if (!fileName.isEmpty()) {
        m_newAvatarPath = fileName;
        m_thumbnail = QImage(m_newAvatarPath);
        m_avatarBtn->setText(QString());
        m_avatarBtn->setIcon(QIcon(m_newAvatarPath));
    }
}

void ContactEditor::saveClicked()
{
    if (!m_manager) {
        qWarning() << "No manager selected; cannot save.";
    } else {
        QContact curr;
        if (m_contactId != QContactLocalId(0))
            curr = m_manager->contact(m_contactId);

        if (m_nameEdit->text().isEmpty()) {
            QMessageBox::information(this, "Failed!", "You must give a name for the contact!");
            return;
        }

        if (m_nameEdit->text() != m_manager->synthesizedDisplayLabel(curr)) {
            // if the name has changed (ie, is different to the synthed label) then save it as a custom label.
            QString saveNameField = nameField();
            if (!saveNameField.isEmpty()) {
                QContactName nm = curr.detail(QContactName::DefinitionName);
                nm.setValue(saveNameField, m_nameEdit->text());
                curr.saveDetail(&nm);
            }
        }

        QContactPhoneNumber phn = curr.detail(QContactPhoneNumber::DefinitionName);
        phn.setNumber(m_phoneEdit->text());
        curr.saveDetail(&phn);

        if (!m_emailEdit->isReadOnly()) {
            QContactEmailAddress em = curr.detail(QContactEmailAddress::DefinitionName);
            em.setEmailAddress(m_emailEdit->text());
            curr.saveDetail(&em);
        }

        if (!m_addrEdit->isReadOnly()) {
            QContactAddress adr = curr.detail(QContactAddress::DefinitionName);
            adr.setStreet(m_addrEdit->text());
            curr.saveDetail(&adr);
        }

        if (m_avatarBtn->isEnabled()) {
            QContactAvatar av = curr.detail(QContactAvatar::DefinitionName);
            av.setAvatar(m_newAvatarPath);
            curr.saveDetail(&av);

            QContactThumbnail thumb = curr.detail(QContactThumbnail::DefinitionName);
            QImage img(m_thumbnail);
            thumb.setThumbnail(img);
            curr.saveDetail(&thumb);
        }

        bool success = m_manager->saveContact(&curr);
        if (success)
            QMessageBox::information(this, "Success!", "Contact saved successfully!");
        else
            QMessageBox::information(this, "Failed!", QString("Failed to save contact!\n(error code %1)").arg(m_manager->error()));
    }

    emit showListPage();
}

void ContactEditor::cancelClicked()
{
    emit showListPage();
}
<commit_msg>Fix compilation of samplephonebook<commit_after>/****************************************************************************
**
** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the Qt Mobility Components.
**
** $QT_BEGIN_LICENSE:LGPL$
** No Commercial Usage
** This file contains pre-release code and may not be distributed.
** You may use this file in accordance with the terms and conditions
** contained in the Technology Preview License Agreement accompanying
** this package.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights.  These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
**
**
**
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/

#include "contacteditor.h"

#include <QtGui>

ContactEditor::ContactEditor(QWidget *parent)
        :QWidget(parent)
{
    m_manager = 0;
    m_contactId = QContactLocalId(0);

#ifdef Q_OS_SYMBIAN
    // In symbian "save" and "cancel" buttons are softkeys.
    m_saveBtn = new QAction("Save", this);
    m_saveBtn->setSoftKeyRole(QAction::PositiveSoftKey);
    addAction(m_saveBtn);
    connect(m_saveBtn, SIGNAL(triggered(bool)), this, SLOT(saveClicked()));
    m_cancelBtn = new QAction("Cancel", this);
    m_cancelBtn->setSoftKeyRole(QAction::NegativeSoftKey);
    addAction(m_cancelBtn);
    connect(m_cancelBtn, SIGNAL(triggered(bool)), this, SLOT(cancelClicked()));
#else
    m_saveBtn = new QPushButton("Save", this);
    connect(m_saveBtn, SIGNAL(clicked()), this, SLOT(saveClicked()));
    m_cancelBtn = new QPushButton("Cancel", this);
    connect(m_cancelBtn, SIGNAL(clicked()), this, SLOT(cancelClicked()));
#endif

    m_nameEdit = new QLineEdit(this);
    m_phoneEdit = new QLineEdit(this);
    m_emailEdit = new QLineEdit(this);
    m_addrEdit = new QLineEdit(this);
    m_avatarBtn = new QPushButton("Add image", this);
    m_avatarBtn->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
    connect(m_avatarBtn, SIGNAL(clicked()), this, SLOT(avatarClicked()));

    QFormLayout *detailsLayout = new QFormLayout;
    detailsLayout->addRow(new QLabel("Name", this));
    detailsLayout->addRow(m_nameEdit);
    detailsLayout->addRow(new QLabel("Phone", this));
    detailsLayout->addRow(m_phoneEdit);
    detailsLayout->addRow(new QLabel("Email", this));
    detailsLayout->addRow(m_emailEdit);
    detailsLayout->addRow(new QLabel("Address", this));
    detailsLayout->addRow(m_addrEdit);
    detailsLayout->addRow(new QLabel("Avatar", this));
    detailsLayout->addRow(m_avatarBtn);
    detailsLayout->setFieldGrowthPolicy(QFormLayout::ExpandingFieldsGrow);
    detailsLayout->setSizeConstraint(QLayout::SetMinAndMaxSize);

    QScrollArea *detailsScrollArea = new QScrollArea(this);
    detailsScrollArea->setWidgetResizable(true);
    QWidget *detailsContainer = new QWidget(detailsScrollArea);
    detailsContainer->setLayout(detailsLayout);
    detailsScrollArea->setWidget(detailsContainer);

#ifndef Q_OS_SYMBIAN
    QHBoxLayout *btnLayout = new QHBoxLayout;
    btnLayout->addWidget(m_saveBtn);
    btnLayout->addWidget(m_cancelBtn);
#endif

    QVBoxLayout *editLayout = new QVBoxLayout;
    editLayout->addWidget(detailsScrollArea);
#ifndef Q_OS_SYMBIAN
    editLayout->addLayout(btnLayout);
#endif

    setLayout(editLayout);
}

ContactEditor::~ContactEditor()
{
}

void ContactEditor::setCurrentContact(QContactManager* manager, QContactLocalId currentId)
{
    m_manager = manager;
    m_contactId = currentId;
    m_newAvatarPath = QString();

    // Clear UI
    m_nameEdit->setText("");
    m_phoneEdit->setText("");
    m_emailEdit->setText("");
    m_addrEdit->setText("");
    m_avatarBtn->setText("Add image");
    m_avatarBtn->setIcon(QIcon());

    if (manager == 0) {
        m_saveBtn->setEnabled(false);
        return;
    }

    // enable the UI.
    m_saveBtn->setEnabled(true);

    // otherwise, build from the contact details.
    QContact curr;
    if (m_contactId != QContactLocalId(0))
        curr = manager->contact(m_contactId);

    // Disable fields & buttons according to what the backend supports
    QMap<QString, QContactDetailDefinition> defs = m_manager->detailDefinitions(QContactType::TypeContact);

    // name
    //QContactName nm = curr.detail(QContactName::DefinitionName);
    if (m_contactId != QContactLocalId(0))
        m_nameEdit->setText(manager->synthesizedDisplayLabel(curr));

    // phonenumber
    QContactPhoneNumber phn = curr.detail(QContactPhoneNumber::DefinitionName);
    m_phoneEdit->setText(phn.value(QContactPhoneNumber::FieldNumber));

    // email
    if (defs.contains(QContactEmailAddress::DefinitionName)) {
        QContactEmailAddress em = curr.detail(QContactEmailAddress::DefinitionName);
        m_emailEdit->setText(em.value(QContactEmailAddress::FieldEmailAddress));
        m_emailEdit->setReadOnly(false);
    } else {
        m_emailEdit->setText("<not supported>");
        m_emailEdit->setReadOnly(true);
    }

    // address
    if (defs.contains(QContactAddress::DefinitionName)) {
        QContactAddress adr = curr.detail(QContactAddress::DefinitionName);
        m_addrEdit->setText(adr.value(QContactAddress::FieldStreet)); // ugly hack.
        m_addrEdit->setReadOnly(false);
    } else {
        m_addrEdit->setText("<not supported>");
        m_addrEdit->setReadOnly(true);
    }

    // avatar button
    if (defs.contains(QContactAvatar::DefinitionName)) {
        QContactAvatar av = curr.detail(QContactAvatar::DefinitionName);
        QContactThumbnail thumb = curr.detail(QContactThumbnail::DefinitionName);
        m_avatarBtn->setText(QString());
        m_avatarBtn->setIcon(QIcon());
        if (thumb.thumbnail().isNull()) {
            if (av.imageUrl().isEmpty()) {
                m_avatarBtn->setText("Add image");
            } else {
                m_avatarBtn->setIcon(QIcon(QPixmap(av.imageUrl().toLocalFile())));
                m_thumbnail = QImage(av.imageUrl().toLocalFile());
            }
        } else {
            m_newAvatarPath = av.imageUrl().toLocalFile();
            m_thumbnail = thumb.thumbnail();
            m_avatarBtn->setIcon(QIcon(QPixmap::fromImage(thumb.thumbnail())));
        }
        m_avatarBtn->setDisabled(false);
    } else {
        m_avatarBtn->setIcon(QIcon());
        m_avatarBtn->setText("<not supported>");
        m_avatarBtn->setDisabled(true);
    }
}

QString ContactEditor::nameField()
{
    // return the field which the name data should be saved in.
    if (!m_manager)
        return QString();

    QMap<QString, QContactDetailDefinition> defs = m_manager->detailDefinitions(QContactType::TypeContact);
    QContactDetailDefinition nameDef = defs.value(QContactName::DefinitionName);
    if (nameDef.fields().keys().contains(QContactName::FieldCustomLabel)) {
        return QString(QLatin1String(QContactName::FieldCustomLabel));
    } else if (nameDef.fields().keys().contains(QContactName::FieldFirstName)) {
        return QString(QLatin1String(QContactName::FieldFirstName));
    } else {
        return QString();
    }
}

void ContactEditor::avatarClicked()
{
    // put up a file dialog, and update the new avatar path.
    QString fileName = QFileDialog::getOpenFileName(this,
       tr("Select Avatar Image"), ".", tr("Image Files (*.png *.jpg *.bmp)"));

    if (!fileName.isEmpty()) {
        m_newAvatarPath = fileName;
        m_thumbnail = QImage(m_newAvatarPath);
        m_avatarBtn->setText(QString());
        m_avatarBtn->setIcon(QIcon(m_newAvatarPath));
    }
}

void ContactEditor::saveClicked()
{
    if (!m_manager) {
        qWarning() << "No manager selected; cannot save.";
    } else {
        QContact curr;
        if (m_contactId != QContactLocalId(0))
            curr = m_manager->contact(m_contactId);

        if (m_nameEdit->text().isEmpty()) {
            QMessageBox::information(this, "Failed!", "You must give a name for the contact!");
            return;
        }

        if (m_nameEdit->text() != m_manager->synthesizedDisplayLabel(curr)) {
            // if the name has changed (ie, is different to the synthed label) then save it as a custom label.
            QString saveNameField = nameField();
            if (!saveNameField.isEmpty()) {
                QContactName nm = curr.detail(QContactName::DefinitionName);
                nm.setValue(saveNameField, m_nameEdit->text());
                curr.saveDetail(&nm);
            }
        }

        QContactPhoneNumber phn = curr.detail(QContactPhoneNumber::DefinitionName);
        phn.setNumber(m_phoneEdit->text());
        curr.saveDetail(&phn);

        if (!m_emailEdit->isReadOnly()) {
            QContactEmailAddress em = curr.detail(QContactEmailAddress::DefinitionName);
            em.setEmailAddress(m_emailEdit->text());
            curr.saveDetail(&em);
        }

        if (!m_addrEdit->isReadOnly()) {
            QContactAddress adr = curr.detail(QContactAddress::DefinitionName);
            adr.setStreet(m_addrEdit->text());
            curr.saveDetail(&adr);
        }

        if (m_avatarBtn->isEnabled()) {
            QContactAvatar av = curr.detail(QContactAvatar::DefinitionName);
            av.setImageUrl(QUrl(m_newAvatarPath));
            curr.saveDetail(&av);

            QContactThumbnail thumb = curr.detail(QContactThumbnail::DefinitionName);
            QImage img(m_thumbnail);
            thumb.setThumbnail(img);
            curr.saveDetail(&thumb);
        }

        bool success = m_manager->saveContact(&curr);
        if (success)
            QMessageBox::information(this, "Success!", "Contact saved successfully!");
        else
            QMessageBox::information(this, "Failed!", QString("Failed to save contact!\n(error code %1)").arg(m_manager->error()));
    }

    emit showListPage();
}

void ContactEditor::cancelClicked()
{
    emit showListPage();
}
<|endoftext|>


<commit_before><commit_msg>Delete Lux.cpp<commit_after><|endoftext|>


<commit_before><commit_msg>Make DRM wizard detect Steam on Linux & OS X (Closes: #18)<commit_after><|endoftext|>


<commit_before>/*
 *
 *    Copyright (c) 2020 Project CHIP Authors
 *
 *    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.
 */

/**
 *    @file
 *          Provides an implementation of the PlatformManager object
 *          for Zephyr platforms.
 */

#if !CONFIG_NORDIC_SECURITY_BACKEND
#include <crypto/CHIPCryptoPAL.h> // nogncheck
#endif                            // !CONFIG_NORDIC_SECURITY_BACKEND

#include <platform/internal/CHIPDeviceLayerInternal.h>

#include <lib/support/logging/CHIPLogging.h>
#include <platform/PlatformManager.h>
#include <platform/Zephyr/DiagnosticDataProviderImpl.h>
#include <platform/internal/GenericPlatformManagerImpl_Zephyr.ipp>

#include <drivers/entropy.h>
#include <malloc.h>

namespace chip {
namespace DeviceLayer {

static K_THREAD_STACK_DEFINE(sChipThreadStack, CHIP_DEVICE_CONFIG_CHIP_TASK_STACK_SIZE);

PlatformManagerImpl PlatformManagerImpl::sInstance{ sChipThreadStack };

static k_timer sOperationalHoursSavingTimer;

#if !CONFIG_NORDIC_SECURITY_BACKEND
static int app_entropy_source(void * data, unsigned char * output, size_t len, size_t * olen)
{
    const struct device * entropy = device_get_binding(DT_CHOSEN_ZEPHYR_ENTROPY_LABEL);
    int ret                       = entropy_get_entropy(entropy, output, len);

    if (ret == 0)
    {
        *olen = len;
    }
    else
    {
        *olen = 0;
    }

    return ret;
}
#endif // !CONFIG_NORDIC_SECURITY_BACKEND

void PlatformManagerImpl::OperationalHoursSavingTimerEventHandler(k_timer * timer)
{
    PlatformMgr().ScheduleWork(UpdateOperationalHours);
}

void PlatformManagerImpl::UpdateOperationalHours(intptr_t arg)
{
    uint64_t upTimeS;

    if (GetDiagnosticDataProvider().GetUpTime(upTimeS) != CHIP_NO_ERROR)
    {
        ChipLogError(DeviceLayer, "Failed to get up time of the node");
        return;
    }

    uint64_t totalOperationalHours = 0;
    const uint32_t upTimeH         = upTimeS / 3600 < UINT32_MAX ? static_cast<uint32_t>(upTimeS / 3600) : UINT32_MAX;
    const uint64_t deltaTime       = upTimeH - sInstance.mSavedOperationalHoursSinceBoot;

    if (ConfigurationMgr().GetTotalOperationalHours(reinterpret_cast<uint32_t &>(totalOperationalHours)) == CHIP_NO_ERROR)
    {
        ConfigurationMgr().StoreTotalOperationalHours(
            totalOperationalHours + deltaTime < UINT32_MAX ? totalOperationalHours + deltaTime : UINT32_MAX);
        sInstance.mSavedOperationalHoursSinceBoot = upTimeH;
    }
    else
    {
        ChipLogError(DeviceLayer, "Failed to get total operational hours of the node");
    }
}

CHIP_ERROR PlatformManagerImpl::_InitChipStack(void)
{
    CHIP_ERROR err;

#if !CONFIG_NORDIC_SECURITY_BACKEND
    // Minimum required from source before entropy is released ( with mbedtls_entropy_func() ) (in bytes)
    const size_t kThreshold = 16;
#endif // !CONFIG_NORDIC_SECURITY_BACKEND

    // Initialize the configuration system.
    err = Internal::ZephyrConfig::Init();
    SuccessOrExit(err);
    SetConfigurationMgr(&ConfigurationManagerImpl::GetDefaultInstance());
    SetDiagnosticDataProvider(&DiagnosticDataProviderImpl::GetDefaultInstance());

#if !CONFIG_NORDIC_SECURITY_BACKEND
    // Add entropy source based on Zephyr entropy driver
    err = chip::Crypto::add_entropy_source(app_entropy_source, NULL, kThreshold);
    SuccessOrExit(err);
#endif // !CONFIG_NORDIC_SECURITY_BACKEND

    // Call _InitChipStack() on the generic implementation base class to finish the initialization process.
    err = Internal::GenericPlatformManagerImpl_Zephyr<PlatformManagerImpl>::_InitChipStack();
    SuccessOrExit(err);

    // Start the timer to periodically save node operational hours.
    k_timer_init(&sOperationalHoursSavingTimer, &PlatformManagerImpl::OperationalHoursSavingTimerEventHandler, nullptr);
    k_timer_user_data_set(&sOperationalHoursSavingTimer, this);
    k_timer_start(&sOperationalHoursSavingTimer, K_HOURS(CONFIG_CHIP_OPERATIONAL_TIME_SAVE_INTERVAL),
                  K_HOURS(CONFIG_CHIP_OPERATIONAL_TIME_SAVE_INTERVAL));

exit:
    return err;
}

} // namespace DeviceLayer
} // namespace chip
<commit_msg>Use DEVICE_DT_GET to obtain chosen entropy device (#19048)<commit_after>/*
 *
 *    Copyright (c) 2020 Project CHIP Authors
 *
 *    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.
 */

/**
 *    @file
 *          Provides an implementation of the PlatformManager object
 *          for Zephyr platforms.
 */

#if !CONFIG_NORDIC_SECURITY_BACKEND
#include <crypto/CHIPCryptoPAL.h> // nogncheck
#endif                            // !CONFIG_NORDIC_SECURITY_BACKEND

#include <platform/internal/CHIPDeviceLayerInternal.h>

#include <lib/support/logging/CHIPLogging.h>
#include <platform/PlatformManager.h>
#include <platform/Zephyr/DiagnosticDataProviderImpl.h>
#include <platform/internal/GenericPlatformManagerImpl_Zephyr.ipp>

#include <drivers/entropy.h>
#include <malloc.h>

namespace chip {
namespace DeviceLayer {

static K_THREAD_STACK_DEFINE(sChipThreadStack, CHIP_DEVICE_CONFIG_CHIP_TASK_STACK_SIZE);

PlatformManagerImpl PlatformManagerImpl::sInstance{ sChipThreadStack };

static k_timer sOperationalHoursSavingTimer;

#if !CONFIG_NORDIC_SECURITY_BACKEND
static int app_entropy_source(void * data, unsigned char * output, size_t len, size_t * olen)
{
    const struct device * entropy = DEVICE_DT_GET(DT_CHOSEN(zephyr_entropy));
    int ret                       = entropy_get_entropy(entropy, output, len);

    if (ret == 0)
    {
        *olen = len;
    }
    else
    {
        *olen = 0;
    }

    return ret;
}
#endif // !CONFIG_NORDIC_SECURITY_BACKEND

void PlatformManagerImpl::OperationalHoursSavingTimerEventHandler(k_timer * timer)
{
    PlatformMgr().ScheduleWork(UpdateOperationalHours);
}

void PlatformManagerImpl::UpdateOperationalHours(intptr_t arg)
{
    uint64_t upTimeS;

    if (GetDiagnosticDataProvider().GetUpTime(upTimeS) != CHIP_NO_ERROR)
    {
        ChipLogError(DeviceLayer, "Failed to get up time of the node");
        return;
    }

    uint64_t totalOperationalHours = 0;
    const uint32_t upTimeH         = upTimeS / 3600 < UINT32_MAX ? static_cast<uint32_t>(upTimeS / 3600) : UINT32_MAX;
    const uint64_t deltaTime       = upTimeH - sInstance.mSavedOperationalHoursSinceBoot;

    if (ConfigurationMgr().GetTotalOperationalHours(reinterpret_cast<uint32_t &>(totalOperationalHours)) == CHIP_NO_ERROR)
    {
        ConfigurationMgr().StoreTotalOperationalHours(
            totalOperationalHours + deltaTime < UINT32_MAX ? totalOperationalHours + deltaTime : UINT32_MAX);
        sInstance.mSavedOperationalHoursSinceBoot = upTimeH;
    }
    else
    {
        ChipLogError(DeviceLayer, "Failed to get total operational hours of the node");
    }
}

CHIP_ERROR PlatformManagerImpl::_InitChipStack(void)
{
    CHIP_ERROR err;

#if !CONFIG_NORDIC_SECURITY_BACKEND
    // Minimum required from source before entropy is released ( with mbedtls_entropy_func() ) (in bytes)
    const size_t kThreshold = 16;
#endif // !CONFIG_NORDIC_SECURITY_BACKEND

    // Initialize the configuration system.
    err = Internal::ZephyrConfig::Init();
    SuccessOrExit(err);
    SetConfigurationMgr(&ConfigurationManagerImpl::GetDefaultInstance());
    SetDiagnosticDataProvider(&DiagnosticDataProviderImpl::GetDefaultInstance());

#if !CONFIG_NORDIC_SECURITY_BACKEND
    // Add entropy source based on Zephyr entropy driver
    err = chip::Crypto::add_entropy_source(app_entropy_source, NULL, kThreshold);
    SuccessOrExit(err);
#endif // !CONFIG_NORDIC_SECURITY_BACKEND

    // Call _InitChipStack() on the generic implementation base class to finish the initialization process.
    err = Internal::GenericPlatformManagerImpl_Zephyr<PlatformManagerImpl>::_InitChipStack();
    SuccessOrExit(err);

    // Start the timer to periodically save node operational hours.
    k_timer_init(&sOperationalHoursSavingTimer, &PlatformManagerImpl::OperationalHoursSavingTimerEventHandler, nullptr);
    k_timer_user_data_set(&sOperationalHoursSavingTimer, this);
    k_timer_start(&sOperationalHoursSavingTimer, K_HOURS(CONFIG_CHIP_OPERATIONAL_TIME_SAVE_INTERVAL),
                  K_HOURS(CONFIG_CHIP_OPERATIONAL_TIME_SAVE_INTERVAL));

exit:
    return err;
}

} // namespace DeviceLayer
} // namespace chip
<|endoftext|>