<commit_before>/***************************************************************************
**
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (testabilitydriver@nokia.com)
**
** This file is part of Testability Driver Qt Agent
**
** If you have questions regarding the use of this file, please contact
** Nokia at testabilitydriver@nokia.com .
**
** 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
** and appearing in the file LICENSE.LGPL included in the packaging
** of this file.
**
****************************************************************************/

#include "tasnativeutils.h"
#include <taslogger.h>
#include <w32std.h>
#include <apgtask.h>
#include <QTimer>
#include <memspydriverclient.h>
#include <e32property.h>
#include <cfclient.h>

class NativeUtils_p
{
public:
    static TBool bringAppToForeground(TApaTask app);
};

/*!
  \class TasNativeUtils
  \brief Symbian platform specific implementation of the interface.
*/

int TasNativeUtils::pidOfActiveWindow(const QHash<QString, TasClient*> clients)
{
    TasLogger::logger()->debug("-> TasNativeUtils::pidOfActiveWindow");

    //do not bother searching if no apps reqistered
    if(clients.isEmpty()){
        return TAS_ERROR_NOT_FOUND;
    }

    const QList<QString>& pids = clients.keys();
    int pid = TAS_ERROR_NOT_FOUND;
    RWsSession wsSession;
    int error = wsSession.Connect();
    if (KErrNone == error) {
        TApaTaskList applicationList(wsSession);

        int i = 0;
        int max = wsSession.NumWindowGroups();
        bool appExists = false;
        do {
            TApaTask foregroundApp = applicationList.FindByPos(i);
            appExists = foregroundApp.Exists();
            if (appExists) {
                RThread foregroundAppThread;
                if (KErrNone == foregroundAppThread.Open(foregroundApp.ThreadId().Id())) {
                    RProcess foregroundAppProcess;
                    if(foregroundAppThread.Process(foregroundAppProcess) == KErrNone){
                        pid = foregroundAppProcess.Id().Id();
                        foregroundAppProcess.Close();
                    }
                    foregroundAppThread.Close();
                }
                else {
                    TasLogger::logger()->error(
                            "   Could not open topmost app thread, ID: " +
                            QString::number(foregroundApp.ThreadId().Id()));
                }
            }
            else {
                TasLogger::logger()->error("   No pos " + QString::number(i) + " app found!");
            }
            i++;
            //break the loop if max windowgroup reached
            //mysterious amount of tasks sometimes occurs causing infinite loops
            if( i > max){
                appExists = false;
            }
        } while (appExists && TAS_ERROR_NOT_FOUND == pid);

        wsSession.Close();
    }
    else {
        TasLogger::logger()->error("   Couldn't connect to WS: " + QString::number(error));
    }
    TasLogger::logger()->debug("<- TasNativeUtils::pidOfActiveWindow");
    return pid;
}

int TasNativeUtils::bringAppToForeground(TasClient& client)
{
    TasLogger::logger()->debug("-> TasNativeUtils::bringAppToForeground");
    int error = TAS_ERROR_NONE;

    RWsSession wsSession;
    error = wsSession.Connect();
    if (KErrNone == error) {
        TasLogger::logger()->debug("   Connected to WS");
        TApaTaskList applicationList(wsSession);
        TBool isOk = EFalse;
        // Find app by UID
        QString applicationUid = client.applicationUid();
        int uidi = applicationUid.toInt();
        //we must chect the uid since in some situation the uid seems
        //to be too big for TInt32 which TUId.iUid is
        //name used if uid cannot be
        if(uidi != 0){
            TasLogger::logger()->debug("App uid ok look for app");
            TUid appUid = TUid::Uid(uidi);
            isOk = NativeUtils_p::bringAppToForeground(applicationList.FindApp(appUid));
        }
        else{
            TasLogger::logger()->debug("App uid invalid look with name " + client.applicationName());
            TPtrC16 str(reinterpret_cast<const TUint16*>(client.applicationName().utf16()));
            HBufC* buffer = str.Alloc();
            isOk = NativeUtils_p::bringAppToForeground(applicationList.FindApp(*buffer));
            delete buffer;
        }

        if(!isOk){
            TasLogger::logger()->error("Application found but it does not exist!");
            error = TAS_ERROR_NOT_FOUND;
        }

        wsSession.Close();
    }
    else {
        TasLogger::logger()->error("   Couldn't connect to WS: " + QString::number(error));
    }
    TasLogger::logger()->debug("<- TasNativeUtils::bringAppToForeground");
    return error;
}

TBool NativeUtils_p::bringAppToForeground(TApaTask app)
{
    TBool value = EFalse;
    if (app.Exists()) {
        TasLogger::logger()->debug("App found bring to foreground");
        app.BringToForeground();
        value = ETrue;
    }
    return value;
}

void TasNativeUtils::changeOrientation()
{
    _LIT( KContextSource, "Sensor" );
    _LIT( KSensorSourceEventOrientation, "Event.Orientation" );
    _LIT( KContextValue, "DisplayRightUp?" );
    CCFContextObject* co = CCFContextObject::NewLC();
    co->SetSourceL( KContextSource );
    co->SetTypeL( KSensorSourceEventOrientation );
    co->SetValueL( KContextValue );
    CCFClient* client = CCFClient::NewLC( *this );
    TInt err = client->PublishContext( *co );
    if( err != KErrNone )
        {
        TasLogger::logger()->error("TasNativeUtils::changeOrientation failed: " +  QString::number(err));
        }
    CleanupStack::PopAndDestroy( client );
    CleanupStack::PopAndDestroy( co );
}
<commit_msg>empty implemtation<commit_after>/***************************************************************************
**
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (testabilitydriver@nokia.com)
**
** This file is part of Testability Driver Qt Agent
**
** If you have questions regarding the use of this file, please contact
** Nokia at testabilitydriver@nokia.com .
**
** 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
** and appearing in the file LICENSE.LGPL included in the packaging
** of this file.
**
****************************************************************************/

#include "tasnativeutils.h"
#include <taslogger.h>
#include <w32std.h>
#include <apgtask.h>
#include <QTimer>
#include <memspydriverclient.h>
#include <e32property.h>
#include <cfclient.h>

class NativeUtils_p
{
public:
    static TBool bringAppToForeground(TApaTask app);
};

/*!
  \class TasNativeUtils
  \brief Symbian platform specific implementation of the interface.
*/

int TasNativeUtils::pidOfActiveWindow(const QHash<QString, TasClient*> clients)
{
    TasLogger::logger()->debug("-> TasNativeUtils::pidOfActiveWindow");

    //do not bother searching if no apps reqistered
    if(clients.isEmpty()){
        return TAS_ERROR_NOT_FOUND;
    }

    const QList<QString>& pids = clients.keys();
    int pid = TAS_ERROR_NOT_FOUND;
    RWsSession wsSession;
    int error = wsSession.Connect();
    if (KErrNone == error) {
        TApaTaskList applicationList(wsSession);

        int i = 0;
        int max = wsSession.NumWindowGroups();
        bool appExists = false;
        do {
            TApaTask foregroundApp = applicationList.FindByPos(i);
            appExists = foregroundApp.Exists();
            if (appExists) {
                RThread foregroundAppThread;
                if (KErrNone == foregroundAppThread.Open(foregroundApp.ThreadId().Id())) {
                    RProcess foregroundAppProcess;
                    if(foregroundAppThread.Process(foregroundAppProcess) == KErrNone){
                        pid = foregroundAppProcess.Id().Id();
                        foregroundAppProcess.Close();
                    }
                    foregroundAppThread.Close();
                }
                else {
                    TasLogger::logger()->error(
                            "   Could not open topmost app thread, ID: " +
                            QString::number(foregroundApp.ThreadId().Id()));
                }
            }
            else {
                TasLogger::logger()->error("   No pos " + QString::number(i) + " app found!");
            }
            i++;
            //break the loop if max windowgroup reached
            //mysterious amount of tasks sometimes occurs causing infinite loops
            if( i > max){
                appExists = false;
            }
        } while (appExists && TAS_ERROR_NOT_FOUND == pid);

        wsSession.Close();
    }
    else {
        TasLogger::logger()->error("   Couldn't connect to WS: " + QString::number(error));
    }
    TasLogger::logger()->debug("<- TasNativeUtils::pidOfActiveWindow");
    return pid;
}

int TasNativeUtils::bringAppToForeground(TasClient& client)
{
    TasLogger::logger()->debug("-> TasNativeUtils::bringAppToForeground");
    int error = TAS_ERROR_NONE;

    RWsSession wsSession;
    error = wsSession.Connect();
    if (KErrNone == error) {
        TasLogger::logger()->debug("   Connected to WS");
        TApaTaskList applicationList(wsSession);
        TBool isOk = EFalse;
        // Find app by UID
        QString applicationUid = client.applicationUid();
        int uidi = applicationUid.toInt();
        //we must chect the uid since in some situation the uid seems
        //to be too big for TInt32 which TUId.iUid is
        //name used if uid cannot be
        if(uidi != 0){
            TasLogger::logger()->debug("App uid ok look for app");
            TUid appUid = TUid::Uid(uidi);
            isOk = NativeUtils_p::bringAppToForeground(applicationList.FindApp(appUid));
        }
        else{
            TasLogger::logger()->debug("App uid invalid look with name " + client.applicationName());
            TPtrC16 str(reinterpret_cast<const TUint16*>(client.applicationName().utf16()));
            HBufC* buffer = str.Alloc();
            isOk = NativeUtils_p::bringAppToForeground(applicationList.FindApp(*buffer));
            delete buffer;
        }

        if(!isOk){
            TasLogger::logger()->error("Application found but it does not exist!");
            error = TAS_ERROR_NOT_FOUND;
        }

        wsSession.Close();
    }
    else {
        TasLogger::logger()->error("   Couldn't connect to WS: " + QString::number(error));
    }
    TasLogger::logger()->debug("<- TasNativeUtils::bringAppToForeground");
    return error;
}

TBool NativeUtils_p::bringAppToForeground(TApaTask app)
{
    TBool value = EFalse;
    if (app.Exists()) {
        TasLogger::logger()->debug("App found bring to foreground");
        app.BringToForeground();
        value = ETrue;
    }
    return value;
}

void TasNativeUtils::changeOrientation()
{
}
<|endoftext|>


<commit_before>#include <map>
#include <string>
#include <vector>

#include "fetest.hh"

#include <cppunit/TestFixture.h>
#include <cppunit/extensions/HelperMacros.h>

CPPUNIT_TEST_SUITE_REGISTRATION (fetest);

void fetest :: setUp (void)
{
}

void fetest :: tearDown (void)
{
}

void fetest :: viterbiTest1 (void)
{
    map<string, double> vocab;
    string str1("a"); string str2("bc");
    vocab[str1] = -1.0;
    vocab[str2] = -2.0;
    string sentence("abc");
    vector<string> best_path;
    int maxlen = 2;
    viterbi(vocab, maxlen, sentence, best_path);
    CPPUNIT_ASSERT_EQUAL(2, (int)best_path.size());
    CPPUNIT_ASSERT_EQUAL(str1, best_path[0]);
    CPPUNIT_ASSERT_EQUAL(str2, best_path[1]);
}

void fetest :: viterbiTest2 (void)
{
    map<string, double> vocab;
    string str1("a"); string str2("bc");
    string str3("ab"); string str4("c");
    vocab[str1] = -1.0;
    vocab[str2] = -2.0;
    vocab[str3] = 0.0;
    vocab[str4] = 0.0;
    string sentence("abc");
    vector<string> best_path;
    int maxlen = 2;
    viterbi(vocab, maxlen, sentence, best_path);
    CPPUNIT_ASSERT_EQUAL(2, (int)best_path.size());
    CPPUNIT_ASSERT_EQUAL(str3, best_path[0]);
    CPPUNIT_ASSERT_EQUAL(str4, best_path[1]);
}

// No possible segmentation
void fetest :: viterbiTest3 (void)
{
    map<string, double> vocab;
    string str1("a");
    vocab[str1] = -1.0;
    string sentence("abc");
    vector<string> best_path;
    int maxlen = 1;
    viterbi(vocab, maxlen, sentence, best_path);
    CPPUNIT_ASSERT_EQUAL(0, (int)best_path.size());
}

// Empty string
void fetest :: viterbiTest4 (void)
{
    map<string, double> vocab;
    string str1("a");
    vocab[str1] = -1.0;
    string sentence("");
    vector<string> best_path;
    int maxlen = 1;
    viterbi(vocab, maxlen, sentence, best_path);
    CPPUNIT_ASSERT_EQUAL(0, (int)best_path.size());
}

// One character sentence
void fetest :: viterbiTest5 (void)
{
    map<string, double> vocab;
    string str1("a");
    vocab[str1] = -1.0;
    string sentence("a");
    vector<string> best_path;
    int maxlen = 1;
    viterbi(vocab, maxlen, sentence, best_path);
    CPPUNIT_ASSERT_EQUAL(1, (int)best_path.size());
    CPPUNIT_ASSERT_EQUAL(str1, best_path[0]);
}

// No segmentation
void fetest :: viterbiTest6 (void)
{
    map<string, double> vocab;
    string str1("a"); string str2("b");
    string str3("c"); string str4("d");
    vocab[str1] = -1.0;
    vocab[str2] = -2.0;
    vocab[str3] = 0.0;
    vocab[str4] = 0.0;
    string sentence("a-bcd");
    vector<string> best_path;
    int maxlen = 1;
    viterbi(vocab, maxlen, sentence, best_path);
    CPPUNIT_ASSERT_EQUAL(0, (int)best_path.size());
}

// Empty string
void fetest :: ForwardBackwardTest1 (void)
{
    map<string, double> vocab;
    string str1("a");
    vocab[str1] = -1.0;
    string sentence("");
    map<string, double> stats;
    forward_backward(vocab, sentence, stats);
    CPPUNIT_ASSERT_EQUAL(0, (int)stats.size());
}

// No segmentation
void fetest :: ForwardBackwardTest2 (void)
{
    map<string, double> vocab;
    string str1("a"); string str2("b");
    string str3("c"); string str4("d");
    vocab[str1] = -1.0;
    vocab[str2] = -2.0;
    vocab[str3] = 0.0;
    vocab[str4] = 0.0;
    string sentence("a-bcd");
    map<string, double> stats;
    forward_backward(vocab, sentence, stats);
    CPPUNIT_ASSERT_EQUAL(0, (int)stats.size());
}

// One character string
void fetest :: ForwardBackwardTest3 (void)
{
    map<string, double> vocab;
    vocab["a"] = -1.0;
    string sentence("a");
    map<string, double> stats;
    forward_backward(vocab, sentence, stats);
    CPPUNIT_ASSERT_EQUAL(1, (int)stats.size());
    CPPUNIT_ASSERT_EQUAL(1.0, stats["a"]);
}

// Two character string, one segmentation
void fetest :: ForwardBackwardTest4 (void)
{
    map<string, double> vocab;
    vocab["a"] = -1.0;
    vocab["b"] = -1.0;
    string sentence("ab");
    map<string, double> stats;
    forward_backward(vocab, sentence, stats);
    CPPUNIT_ASSERT_EQUAL(2, (int)stats.size());
    CPPUNIT_ASSERT_EQUAL(1.0, stats["b"]);
    CPPUNIT_ASSERT_EQUAL(1.0, stats["a"]);
}

// Two character string, two segmentations
// Independent paths
void fetest :: ForwardBackwardTest5 (void)
{
    map<string, double> vocab;
    vocab["a"] = -1.0;
    vocab["b"] = -1.0;
    vocab["ab"] = -1.0;
    string sentence("ab");
    map<string, double> stats;
    forward_backward(vocab, sentence, stats);
    CPPUNIT_ASSERT_EQUAL(3, (int)stats.size());
    CPPUNIT_ASSERT_EQUAL(0.25, stats["b"]);
    CPPUNIT_ASSERT_EQUAL(0.25, stats["a"]);
    CPPUNIT_ASSERT_EQUAL(0.75, stats["ab"]);
}

<commit_msg>Better checks for doubles.<commit_after>#include <map>
#include <string>
#include <vector>

#include "fetest.hh"

#include <cppunit/TestFixture.h>
#include <cppunit/extensions/HelperMacros.h>

double DBL_ACCURACY = 0.0001;

CPPUNIT_TEST_SUITE_REGISTRATION (fetest);

void fetest :: setUp (void)
{
}

void fetest :: tearDown (void)
{
}

void fetest :: viterbiTest1 (void)
{
    map<string, double> vocab;
    string str1("a"); string str2("bc");
    vocab[str1] = -1.0;
    vocab[str2] = -2.0;
    string sentence("abc");
    vector<string> best_path;
    int maxlen = 2;
    viterbi(vocab, maxlen, sentence, best_path);
    CPPUNIT_ASSERT_EQUAL(2, (int)best_path.size());
    CPPUNIT_ASSERT_EQUAL(str1, best_path[0]);
    CPPUNIT_ASSERT_EQUAL(str2, best_path[1]);
}

void fetest :: viterbiTest2 (void)
{
    map<string, double> vocab;
    string str1("a"); string str2("bc");
    string str3("ab"); string str4("c");
    vocab[str1] = -1.0;
    vocab[str2] = -2.0;
    vocab[str3] = 0.0;
    vocab[str4] = 0.0;
    string sentence("abc");
    vector<string> best_path;
    int maxlen = 2;
    viterbi(vocab, maxlen, sentence, best_path);
    CPPUNIT_ASSERT_EQUAL(2, (int)best_path.size());
    CPPUNIT_ASSERT_EQUAL(str3, best_path[0]);
    CPPUNIT_ASSERT_EQUAL(str4, best_path[1]);
}

// No possible segmentation
void fetest :: viterbiTest3 (void)
{
    map<string, double> vocab;
    string str1("a");
    vocab[str1] = -1.0;
    string sentence("abc");
    vector<string> best_path;
    int maxlen = 1;
    viterbi(vocab, maxlen, sentence, best_path);
    CPPUNIT_ASSERT_EQUAL(0, (int)best_path.size());
}

// Empty string
void fetest :: viterbiTest4 (void)
{
    map<string, double> vocab;
    string str1("a");
    vocab[str1] = -1.0;
    string sentence("");
    vector<string> best_path;
    int maxlen = 1;
    viterbi(vocab, maxlen, sentence, best_path);
    CPPUNIT_ASSERT_EQUAL(0, (int)best_path.size());
}

// One character sentence
void fetest :: viterbiTest5 (void)
{
    map<string, double> vocab;
    string str1("a");
    vocab[str1] = -1.0;
    string sentence("a");
    vector<string> best_path;
    int maxlen = 1;
    viterbi(vocab, maxlen, sentence, best_path);
    CPPUNIT_ASSERT_EQUAL(1, (int)best_path.size());
    CPPUNIT_ASSERT_EQUAL(str1, best_path[0]);
}

// No segmentation
void fetest :: viterbiTest6 (void)
{
    map<string, double> vocab;
    string str1("a"); string str2("b");
    string str3("c"); string str4("d");
    vocab[str1] = -1.0;
    vocab[str2] = -2.0;
    vocab[str3] = 0.0;
    vocab[str4] = 0.0;
    string sentence("a-bcd");
    vector<string> best_path;
    int maxlen = 1;
    viterbi(vocab, maxlen, sentence, best_path);
    CPPUNIT_ASSERT_EQUAL(0, (int)best_path.size());
}

// Empty string
void fetest :: ForwardBackwardTest1 (void)
{
    map<string, double> vocab;
    string str1("a");
    vocab[str1] = -1.0;
    string sentence("");
    map<string, double> stats;
    forward_backward(vocab, sentence, stats);
    CPPUNIT_ASSERT_EQUAL(0, (int)stats.size());
}

// No segmentation
void fetest :: ForwardBackwardTest2 (void)
{
    map<string, double> vocab;
    string str1("a"); string str2("b");
    string str3("c"); string str4("d");
    vocab[str1] = -1.0;
    vocab[str2] = -2.0;
    vocab[str3] = 0.0;
    vocab[str4] = 0.0;
    string sentence("a-bcd");
    map<string, double> stats;
    forward_backward(vocab, sentence, stats);
    CPPUNIT_ASSERT_EQUAL(0, (int)stats.size());
}

// One character string
void fetest :: ForwardBackwardTest3 (void)
{
    map<string, double> vocab;
    vocab["a"] = -1.0;
    string sentence("a");
    map<string, double> stats;
    forward_backward(vocab, sentence, stats);
    CPPUNIT_ASSERT_EQUAL(1, (int)stats.size());
    CPPUNIT_ASSERT_EQUAL(1.0, stats["a"]);
}

// Two character string, one segmentation
void fetest :: ForwardBackwardTest4 (void)
{
    map<string, double> vocab;
    vocab["a"] = -1.0;
    vocab["b"] = -1.0;
    string sentence("ab");
    map<string, double> stats;
    forward_backward(vocab, sentence, stats);
    CPPUNIT_ASSERT_EQUAL(2, (int)stats.size());
    CPPUNIT_ASSERT_EQUAL(1.0, stats["b"]);
    CPPUNIT_ASSERT_EQUAL(1.0, stats["a"]);
}

// Two character string, two segmentations
// Independent paths
void fetest :: ForwardBackwardTest5 (void)
{
    map<string, double> vocab;
    vocab["a"] = -1.0;
    vocab["b"] = -1.0;
    vocab["ab"] = -2.0;
    string sentence("ab");
    map<string, double> stats;
    forward_backward(vocab, sentence, stats);
    CPPUNIT_ASSERT_EQUAL(3, (int)stats.size());
    CPPUNIT_ASSERT_DOUBLES_EQUAL( 0.50, stats["ab"], DBL_ACCURACY );
    CPPUNIT_ASSERT_DOUBLES_EQUAL( 0.50, stats["b"], DBL_ACCURACY );
    CPPUNIT_ASSERT_DOUBLES_EQUAL( 0.50, stats["a"], DBL_ACCURACY );
}

<|endoftext|>


<commit_before>/*
 * The Apache Software License, Version 1.1
 *
 * Copyright (c) 1999-2000 The Apache Software Foundation.  All rights
 * reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 *
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in
 *    the documentation and/or other materials provided with the
 *    distribution.
 *
 * 3. The end-user documentation included with the redistribution,
 *    if any, must include the following acknowledgment:
 *       "This product includes software developed by the
 *        Apache Software Foundation (http://www.apache.org/)."
 *    Alternately, this acknowledgment may appear in the software itself,
 *    if and wherever such third-party acknowledgments normally appear.
 *
 * 4. The names "Xerces" and "Apache Software Foundation" must
 *    not be used to endorse or promote products derived from this
 *    software without prior written permission. For written
 *    permission, please contact apache\@apache.org.
 *
 * 5. Products derived from this software may not be called "Apache",
 *    nor may "Apache" appear in their name, without prior written
 *    permission of the Apache Software Foundation.
 *
 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 * ====================================================================
 *
 * This software consists of voluntary contributions made by many
 * individuals on behalf of the Apache Software Foundation, and was
 * originally based on software copyright (c) 1999, International
 * Business Machines, Inc., http://www.ibm.com .  For more information
 * on the Apache Software Foundation, please see
 * <http://www.apache.org/>.
 */

/**
 * $Log$
 * Revision 1.4  2000/05/15 22:31:11  andyh
 * Replace #include<memory.h> with <string.h> everywhere.
 *
 * Revision 1.3  2000/02/06 07:47:47  rahulj
 * Year 2K copyright swat.
 *
 * Revision 1.2  1999/11/23 01:04:19  roddey
 * Updates to some of the internal VC++ project files and some small
 * fixes to make XMLBuffer correctly character size agnostic.
 *
 * Revision 1.1.1.1  1999/11/09 01:08:29  twl
 * Initial checkin
 *
 * Revision 1.2  1999/11/08 20:44:35  rahul
 * Swat for adding in Product name and CVS comment log variable.
 *
 */

// ---------------------------------------------------------------------------
//  Includes
// ---------------------------------------------------------------------------
#include <util/RuntimeException.hpp>
#include <util/XMLString.hpp>
#include <framework/XMLBuffer.hpp>
#include <string.h>

// ---------------------------------------------------------------------------
//  XMLBuffer: Buffer management
// ---------------------------------------------------------------------------
void XMLBuffer::append(const XMLCh* const chars, const unsigned int count)
{
    unsigned int actualCount = count;
    if (!count)
        actualCount = XMLString::stringLen(chars);
    insureCapacity(actualCount);
    memcpy(&fBuffer[fIndex], chars, actualCount * sizeof(XMLCh));
    fIndex += actualCount;
}

void XMLBuffer::set(const XMLCh* const chars, const unsigned int count)
{
    unsigned int actualCount = count;
    if (!count)
        actualCount = XMLString::stringLen(chars);
    fIndex = 0;
    insureCapacity(actualCount);
    memcpy(fBuffer, chars, actualCount * sizeof(XMLCh));
    fIndex = actualCount;
}

// ---------------------------------------------------------------------------
//  XMLBuffer: Private helper methods
// ---------------------------------------------------------------------------
void XMLBuffer::expand()
{
    unsigned int newCap = (unsigned int)(fCapacity * 1.5);

    // Allocate the new buffer
    XMLCh* newBuf = new XMLCh[newCap + 1];

    // Copy over the old stuff
    memcpy(newBuf, fBuffer, fCapacity * sizeof(XMLCh));

    // Clean up old buffer and store new stuff
    delete [] fBuffer;
    fBuffer = newBuf;
    fCapacity = newCap;
}

void XMLBuffer::insureCapacity(const unsigned int extraNeeded)
{
    // If we can handle it, do nothing yet
    if (fIndex + extraNeeded < fCapacity)
        return;

    // Oops, not enough room. Calc new capacity and allocate new buffer
    const unsigned int newCap = (unsigned int)((fIndex + fCapacity) * 1.25);
    XMLCh* newBuf = new XMLCh[newCap+1];

    // Copy over the old stuff
    memcpy(newBuf, fBuffer, fCapacity * sizeof(XMLCh));

    // Clean up old buffer and store new stuff
    delete [] fBuffer;
    fBuffer = newBuf;
    fCapacity = newCap;
}
<commit_msg>Fix error in growing of XMLBuffer from within ensureCapacity() Fixes crash pointed out by Simon Fell.<commit_after>/*
 * The Apache Software License, Version 1.1
 *
 * Copyright (c) 1999-2000 The Apache Software Foundation.  All rights
 * reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 *
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in
 *    the documentation and/or other materials provided with the
 *    distribution.
 *
 * 3. The end-user documentation included with the redistribution,
 *    if any, must include the following acknowledgment:
 *       "This product includes software developed by the
 *        Apache Software Foundation (http://www.apache.org/)."
 *    Alternately, this acknowledgment may appear in the software itself,
 *    if and wherever such third-party acknowledgments normally appear.
 *
 * 4. The names "Xerces" and "Apache Software Foundation" must
 *    not be used to endorse or promote products derived from this
 *    software without prior written permission. For written
 *    permission, please contact apache\@apache.org.
 *
 * 5. Products derived from this software may not be called "Apache",
 *    nor may "Apache" appear in their name, without prior written
 *    permission of the Apache Software Foundation.
 *
 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 * ====================================================================
 *
 * This software consists of voluntary contributions made by many
 * individuals on behalf of the Apache Software Foundation, and was
 * originally based on software copyright (c) 1999, International
 * Business Machines, Inc., http://www.ibm.com .  For more information
 * on the Apache Software Foundation, please see
 * <http://www.apache.org/>.
 */

/**
 * $Log$
 * Revision 1.5  2000/08/17 00:04:50  andyh
 * Fix error in growing of XMLBuffer from within ensureCapacity()
 * Fixes crash pointed out by Simon Fell.
 *
 * Revision 1.4  2000/05/15 22:31:11  andyh
 * Replace #include<memory.h> with <string.h> everywhere.
 *
 * Revision 1.3  2000/02/06 07:47:47  rahulj
 * Year 2K copyright swat.
 *
 * Revision 1.2  1999/11/23 01:04:19  roddey
 * Updates to some of the internal VC++ project files and some small
 * fixes to make XMLBuffer correctly character size agnostic.
 *
 * Revision 1.1.1.1  1999/11/09 01:08:29  twl
 * Initial checkin
 *
 * Revision 1.2  1999/11/08 20:44:35  rahul
 * Swat for adding in Product name and CVS comment log variable.
 *
 */

// ---------------------------------------------------------------------------
//  Includes
// ---------------------------------------------------------------------------
#include <util/RuntimeException.hpp>
#include <util/XMLString.hpp>
#include <framework/XMLBuffer.hpp>
#include <string.h>

// ---------------------------------------------------------------------------
//  XMLBuffer: Buffer management
// ---------------------------------------------------------------------------
void XMLBuffer::append(const XMLCh* const chars, const unsigned int count)
{
    unsigned int actualCount = count;
    if (!count)
        actualCount = XMLString::stringLen(chars);
    insureCapacity(actualCount);
    memcpy(&fBuffer[fIndex], chars, actualCount * sizeof(XMLCh));
    fIndex += actualCount;
}

void XMLBuffer::set(const XMLCh* const chars, const unsigned int count)
{
    unsigned int actualCount = count;
    if (!count)
        actualCount = XMLString::stringLen(chars);
    fIndex = 0;
    insureCapacity(actualCount);
    memcpy(fBuffer, chars, actualCount * sizeof(XMLCh));
    fIndex = actualCount;
}

// ---------------------------------------------------------------------------
//  XMLBuffer: Private helper methods
// ---------------------------------------------------------------------------
void XMLBuffer::expand()
{
    unsigned int newCap = (unsigned int)(fCapacity * 1.5);

    // Allocate the new buffer
    XMLCh* newBuf = new XMLCh[newCap + 1];

    // Copy over the old stuff
    memcpy(newBuf, fBuffer, fCapacity * sizeof(XMLCh));

    // Clean up old buffer and store new stuff
    delete [] fBuffer;
    fBuffer = newBuf;
    fCapacity = newCap;
}

void XMLBuffer::insureCapacity(const unsigned int extraNeeded)
{
    // If we can handle it, do nothing yet
    if (fIndex + extraNeeded < fCapacity)
        return;

    // Oops, not enough room. Calc new capacity and allocate new buffer
    const unsigned int newCap = (unsigned int)((fIndex + extraNeeded) * 1.25);
    XMLCh* newBuf = new XMLCh[newCap+1];

    // Copy over the old stuff
    memcpy(newBuf, fBuffer, fCapacity * sizeof(XMLCh));

    // Clean up old buffer and store new stuff
    delete [] fBuffer;
    fBuffer = newBuf;
    fCapacity = newCap;
}
<|endoftext|>


<commit_before>#include "xcint.hpp"

static struct alias_data aliases_array[XC_MAX_ALIASES] =
{
  {"null","No functional",{{"slaterx",0.0}} },
  {"lda","Slater exchange and VWN5 correlation",{{"slaterx",1.0},{"vwn5c",1.0}} },
  {"blyp","Becke exchange and LYP correlation",{{"beckex",1.0},{"lypc",1.0}} },
  {"pbe","PBE exchange and correlation",{{"pbex",1.0},{"pbec",1.0}} },
  {"bp86","Becke-Perdew 1986",{{"beckex",1.0},{"p86c",1.0}} },
  {"kt1","Keal-Tozer 2",{{"slaterx",1.},{"ktx",-0.006},{"vwn5c",1.}} },
  {"kt2","Keal-Tozer 2",{{"slaterx",1.07173},{"ktx",-0.006},{"vwn5c",0.576727}} },
  {"kt3","Keal-Tozer 3",{{"slaterx",1.092},{"ktx",-0.004},{"optxcorr",-0.925452},{"lypc",0.864409}} },
  {"ldaerf","Short-range exchange and correlation LDA functional",{{"ldaerfx",1.0},{"ldaerfc",1.0}}},
  // Hybrid Functionals
  {"pbe0","Perdew-Burke-Ernzerhof",{{"pbex",0.75},{"pbec",1.0},{"exx",0.25}} },
  {"b3lyp","Becke-3-paramater-LYP (VWN5 form)", {{"slaterx",0.80},{"beckecorrx",0.72},{"lypc",0.81},{"vwn5c",0.19},{"exx",0.20}} },
  {"m06","M06", {{"m06c",1.0},{"m06x",1.0}} },
  {"m06-2x","M06 2X", {{"m06x2c",1.0},{"m06x2x",1.0}} },
  {"m06L","M06 L", {{"m06lc",1.0},{"m06lx",1.0}} },
  {"b3lyp-g","Becke-3-paramater-LYP (VWN3 form)", {{"slaterx",0.80},{"beckecorrx",0.72},{"lypc",0.81},{"vwn3c",0.19},{"exx",0.20}} },
  {"b3p86","Becke-3-paramater-LYP (VWN5 form)", {{"slaterx",0.80},{"beckecorrx",0.72},{"p86c",0.81},{"vwn5c",1.0},{"exx",0.20}} },
  {"b3p86-g","Becke-3-paramater-LYP (VWN3 form)", {{"slaterx",0.80},{"beckecorrx",0.72},{"p86c",0.81},{"vwn3c",1.0},{"exx",0.20}} },
  {"bpw91","Becke 88 exchange+PW91",{{"beckex",1.0},{"pw91c",1.0}} },
  {"b97","B97 exchange and correlation", {{"b97x",1.0},{"b97c",1.0},{"exx",0.1943}} },
  {"b97-1","B97-1 exchange and correlation", {{"b97_1x",1.0},{"b97_1c",1.0},{"exx",0.21}} },
  {"b97_2","B97-2 exchange and correlation", {{"b97_2x",1.0},{"b97_2c",1.0},{"exx",0.21}} },
  // Some of these are there to match the names used in Dalton
  {"vwn","VWN5 correlation",{{"vwn5c",1.0}}},
  {"vwn3","VWN5 correlation",{{"vwn3c",1.0}}},
  {"svwn","Slater exchange and VWN5 correlation",{{"slaterx",1.0},{"vwn5c",1.0}} },
  {"svwn5","Slater exchange and VWN5 correlation",{{"slaterx",1.0},{"vwn5c",1.0}} },
  {"svwn3","Slater exchange and VWN3 correlation",{{"slaterx",1.0},{"vwn3c",1.0}} },
  {"becke","Becke exchange",{{"beckecorrx",1.0}}},
  {"slater","Slater exchange",{{"slaterx",1.0}}},
};

// TODO: OLYP

struct alias_data *xcint_aliases = aliases_array;
<commit_msg>add camb3lyp alias<commit_after>#include "xcint.hpp"

static struct alias_data aliases_array[XC_MAX_ALIASES] =
{
  {"null","No functional",{{"slaterx",0.0}} },
  {"lda","Slater exchange and VWN5 correlation",{{"slaterx",1.0},{"vwn5c",1.0}} },
  {"blyp","Becke exchange and LYP correlation",{{"beckex",1.0},{"lypc",1.0}} },
  {"pbe","PBE exchange and correlation",{{"pbex",1.0},{"pbec",1.0}} },
  {"bp86","Becke-Perdew 1986",{{"beckex",1.0},{"p86c",1.0}} },
  {"kt1","Keal-Tozer 2",{{"slaterx",1.},{"ktx",-0.006},{"vwn5c",1.}} },
  {"kt2","Keal-Tozer 2",{{"slaterx",1.07173},{"ktx",-0.006},{"vwn5c",0.576727}} },
  {"kt3","Keal-Tozer 3",{{"slaterx",1.092},{"ktx",-0.004},{"optxcorr",-0.925452},{"lypc",0.864409}} },
  {"ldaerf","Short-range exchange and correlation LDA functional",{{"ldaerfx",1.0},{"ldaerfc",1.0}}},
  // Hybrid Functionals
  {"pbe0","Perdew-Burke-Ernzerhof",{{"pbex",0.75},{"pbec",1.0},{"exx",0.25}} },
  {"b3lyp","Becke-3-paramater-LYP (VWN5 form)", {{"slaterx",0.80},{"beckecorrx",0.72},{"lypc",0.81},{"vwn5c",0.19},{"exx",0.20}} },
  {"m06","M06", {{"m06c",1.0},{"m06x",1.0}} },
  {"m06-2x","M06 2X", {{"m06x2c",1.0},{"m06x2x",1.0}} },
  {"m06L","M06 L", {{"m06lc",1.0},{"m06lx",1.0}} },
  {"b3lyp-g","Becke-3-paramater-LYP (VWN3 form)", {{"slaterx",0.80},{"beckecorrx",0.72},{"lypc",0.81},{"vwn3c",0.19},{"exx",0.20}} },
  {"b3p86","Becke-3-paramater-LYP (VWN5 form)", {{"slaterx",0.80},{"beckecorrx",0.72},{"p86c",0.81},{"vwn5c",1.0},{"exx",0.20}} },
  {"b3p86-g","Becke-3-paramater-LYP (VWN3 form)", {{"slaterx",0.80},{"beckecorrx",0.72},{"p86c",0.81},{"vwn3c",1.0},{"exx",0.20}} },
  {"bpw91","Becke 88 exchange+PW91",{{"beckex",1.0},{"pw91c",1.0}} },
  {"b97","B97 exchange and correlation", {{"b97x",1.0},{"b97c",1.0},{"exx",0.1943}} },
  {"b97-1","B97-1 exchange and correlation", {{"b97_1x",1.0},{"b97_1c",1.0},{"exx",0.21}} },
  {"b97_2","B97-2 exchange and correlation", {{"b97_2x",1.0},{"b97_2c",1.0},{"exx",0.21}} },
  {"camb3lyp","CAM-B3LYP",{{"cam_alpha",0.19},{"cam_beta",0.46},{"rangesep_mu",0.33},{"beckecamx",1.0},{"vwn5c",0.19},{"lypc",0.81},{"exx",1.0}},
  // Some of these are there to match the names used in Dalton
  {"vwn","VWN5 correlation",{{"vwn5c",1.0}}},
  {"vwn3","VWN5 correlation",{{"vwn3c",1.0}}},
  {"svwn","Slater exchange and VWN5 correlation",{{"slaterx",1.0},{"vwn5c",1.0}} },
  {"svwn5","Slater exchange and VWN5 correlation",{{"slaterx",1.0},{"vwn5c",1.0}} },
  {"svwn3","Slater exchange and VWN3 correlation",{{"slaterx",1.0},{"vwn3c",1.0}} },
  {"becke","Becke exchange",{{"beckecorrx",1.0}}},
  {"slater","Slater exchange",{{"slaterx",1.0}}},
};

// TODO: OLYP

struct alias_data *xcint_aliases = aliases_array;
<|endoftext|>


<commit_before>/** @file gsSmoother.cpp

    @brief Provides Multigrid smoothers.

    This file is part of the G+Smo library.

    This Source Code Form is subject to the terms of the Mozilla Public
    License, v. 2.0. If a copy of the MPL was not distributed with this
    file, You can obtain one at http://mozilla.org/MPL/2.0/.

    Author(s): C. Hofreither
*/
#include <gsSolver/gsSmoother.h>
#include <gsCore/gsLinearAlgebra.h>

namespace gismo
{

// smoothers

void dampedRichardsonSweep(const Eigen::SparseMatrix<real_t>& A, gsMatrix<real_t>& x, const gsMatrix<real_t>& f, real_t tau = (real_t)(1))
{
    assert( A.rows() == x.rows() && x.rows() == f.rows() );
    assert( A.cols() == A.rows() && x.cols() == 1 && f.cols() == 1);

    gsMatrix<real_t> temp = f - A * x;
    x += tau * temp;
}

void dampedRichardsonSweepBoundary(const Eigen::SparseMatrix<real_t>& A, gsMatrix<real_t>& x, const gsMatrix<real_t>& f, real_t tau, int numBdNodes)
{
    assert( A.rows() == x.rows() && x.rows() == f.rows() );
    assert( A.cols() == A.rows() && x.cols() == 1 && f.cols() == 1);

    gsMatrix<real_t> temp = f - A * x;
    for (int i = 0; i < A.outerSize(); ++i)
    {
        if (i < numBdNodes || i >= A.outerSize() - numBdNodes)
            x(i) += tau * temp(i);
    }
}

// assumes symmetric matrix
void kaczmarzSweepBoundary(const Eigen::SparseMatrix<real_t>& A, gsMatrix<real_t>& x, const gsMatrix<real_t>& f, real_t tau, int numBdNodes)
{
    assert( A.rows() == x.rows() && x.rows() == f.rows() );
    assert( A.cols() == A.rows() && x.cols() == 1 && f.cols() == 1);

    for (int eq = 0; eq < A.outerSize(); ++eq)
    {
        if (!(eq < numBdNodes || eq >= A.outerSize() - numBdNodes))
            continue;

        real_t Asq = 0;
        real_t Aeqx = 0;

        for (Eigen::SparseMatrix<real_t>::InnerIterator it(A,eq); it; ++it)
        {
            Asq += it.value() * it.value();         // compute squared norm of A_eq
            Aeqx += it.value() * x(it.index());     // compute A_eq . x
        }

        const real_t beta = (f(eq) - Aeqx) / Asq;

        for (Eigen::SparseMatrix<real_t>::InnerIterator it(A,eq); it; ++it)
        {
            x(it.index()) += beta * it.value();     // add beta * A_eq
        }
    }
}

void jacobiSweep(const Eigen::SparseMatrix<real_t>& A, gsMatrix<real_t>& x, const gsMatrix<real_t>& f)
{
    assert( A.rows() == x.rows() && x.rows() == f.rows() );
    assert( A.cols() == A.rows() && x.cols() == 1 && f.cols() == 1);

    gsMatrix<real_t> temp = f - A * x;
    temp.array() /= A.diagonal().array();
    x += temp;
}

void dampedJacobiSweep(const Eigen::SparseMatrix<real_t>& A, gsMatrix<real_t>& x, const gsMatrix<real_t>& f, real_t tau = (real_t)(1.0/2.0))
{
    assert( A.rows() == x.rows() && x.rows() == f.rows() );
    assert( A.cols() == A.rows() && x.cols() == 1 && f.cols() == 1);

    gsMatrix<real_t> temp = f - A * x;
    temp.array() /= A.diagonal().array();
    x += tau * temp;
}

void dampedPreRichardsonSweep(const Eigen::SparseMatrix<real_t>& A, const Eigen::SparseMatrix<real_t>& P, gsMatrix<real_t>& x, const gsMatrix<real_t>& f, real_t tau)
{
    assert( A.rows() == x.rows() && x.rows() == f.rows() );
    assert( A.cols() == A.rows() && x.cols() == 1 && f.cols() == 1);

    gsSparseSolver<>::CGDiagonal solver;
    gsMatrix<real_t> corr;
    corr = f - A * x;
    corr = solver.compute( P ).setTolerance(1e-3).solve(corr).eval();
    //corr.array() *= P.diagonal().array();
    x += tau * corr;
}

void dampedPreJacobiSweep(const Eigen::SparseMatrix<real_t>& A, const Eigen::SparseMatrix<real_t>& P, gsMatrix<real_t>& x, const gsMatrix<real_t>& f, real_t tau = (real_t)(1.0/2.0))
{
    assert( A.rows() == x.rows() && x.rows() == f.rows() );
    assert( A.cols() == A.rows() && x.cols() == 1 && f.cols() == 1);

    //gsMatrix<real_t> temp = f - A * x;
    //temp.array() /= A.diagonal().array();
    //x = tau * temp;

#if 0
    // original version
    gsMatrix<real_t> corr;
    corr = f - A * x;
    corr.array() /= A.diagonal().array();

    corr = gsSparseSolver<>::CGDiagonal( P ).setTolerance(1e-3).solve(corr).eval();
    corr.array() *= P.diagonal().array();
#else
    // symmetricized version
    gsMatrix<real_t> corr;
    corr = f - A * x;

    corr.array() /= A.diagonal().array().sqrt();
    corr.array() *= P.diagonal().array().sqrt();

    corr = gsSparseSolver<>::CGDiagonal( P ).setTolerance(1e-3).solve(corr).eval();

    corr.array() *= P.diagonal().array().sqrt();
    corr.array() /= A.diagonal().array().sqrt();
#endif

    x += tau * corr;
}

void gaussSeidelSweep(const Eigen::SparseMatrix<real_t>& A, gsMatrix<real_t>& x, const gsMatrix<real_t>& f)
{
    assert( A.rows() == x.rows() && x.rows() == f.rows() );
    assert( A.cols() == A.rows() && x.cols() == 1 && f.cols() == 1);

    // A is supposed to be symmetric, so it doesn't matter if it's stored in row- or column-major order
    for (int i = 0; i < A.outerSize(); ++i)
    {
        real_t diag = real_t(0.0);
        real_t sum = real_t(0.0);

        for (Eigen::SparseMatrix<real_t>::InnerIterator it(A,i); it; ++it)
        {
            sum += it.value() * x( it.index() );        // compute A.x
            if (it.index() == i)
                diag = it.value();
        }

        x(i) += (f(i) - sum) / diag;
    }
}

void reverseGaussSeidelSweep(const Eigen::SparseMatrix<real_t>& A, gsMatrix<real_t>& x, const gsMatrix<real_t>& f)
{
    assert( A.rows() == x.rows() && x.rows() == f.rows() );
    assert( A.cols() == A.rows() && x.cols() == 1 && f.cols() == 1);

    // A is supposed to be symmetric, so it doesn't matter if it's stored in row- or column-major order
    for (int i = A.outerSize() - 1; i >= 0; --i)
    {
        real_t diag = real_t(0.0);
        real_t sum = real_t(0.0);

        for (Eigen::SparseMatrix<real_t>::InnerIterator it(A,i); it; ++it)
        {
            sum += it.value() * x( it.index() );        // compute A.x
            if (it.index() == i)
                diag = it.value();
        }

        x(i) += (f(i) - sum) / diag;
    }
}

void gaussSeidelSingleBlock(const Eigen::SparseMatrix<real_t>& A, gsMatrix<real_t>& x, const gsMatrix<real_t>& f, gsVector<index_t>& DoFs)
{
    //Sort from lowest to highes
    DoFs.sortByColumn(0);
    const index_t size = DoFs.rows();

    GISMO_ASSERT ( DoFs(size-1)< A.cols(), "The given DoF is higher than the size of the matrix");

    gsMatrix<real_t> Dblock(size, size);
    gsMatrix<real_t> residual(size, 1);
    for (int i = 0; i< size; i++)
    {
        residual(i,0) = f(DoFs(i),0) - (A.block(DoFs(i), 0, 1, A.cols())*x).value();
        Dblock.block(i,0,1,size) = A.block(DoFs(i), DoFs(i)-i, 1, size);
    }
    //Multiply residual with the inverse of the diagonal block
    residual = Dblock.inverse()*residual;

    //Update
    for (int i = 0; i< size; i++)
       x(DoFs(i),0) += residual(i,0);
}

void preGaussSeidelSweep(const Eigen::SparseMatrix<real_t>& A, const Eigen::SparseMatrix<real_t>& P, gsMatrix<real_t>& x, const gsMatrix<real_t>& f, real_t tau, bool reverse)
{
    assert( A.rows() == x.rows() && x.rows() == f.rows() );
    assert( A.cols() == A.rows() && x.cols() == 1 && f.cols() == 1);

    gsMatrix<real_t> corr;
    corr.setZero( x.rows(), 1 );

    //const int start_i = reverse ? A.outerSize() - 1 : 0                 ;
    //const int end_i   = reverse ? 0                 : A.outerSize() - 1 ;
    //const int inc_i   = reverse ? -1                : 1                 ;

    // A is supposed to be symmetric, so it doesn't matter if it's stored in row- or column-major order
    for (int i = 0; i < A.outerSize(); ++i)
    {
        real_t diag = real_t(0.0);
        real_t sum = real_t(0.0);

        for (Eigen::SparseMatrix<real_t>::InnerIterator it(A,i); it; ++it)
        {
            sum += it.value() * (x( it.index() ) + corr( it.index() ));        // compute A.x
            if (it.index() == i)
                diag = it.value();
        }

        corr(i) = (f(i) - sum) / diag;
    }

    corr = gsSparseSolver<>::CGDiagonal( P )
            .setTolerance(1e-3).solve(corr).eval();
    x.array() += tau * /*P.diagonal().array() * */ corr.array();
}

////////////////////////////////////////////////////////////////////////////////
// smoother class implementations
////////////////////////////////////////////////////////////////////////////////

void gsRichardsonSmoother::apply(const Eigen::SparseMatrix<real_t>& A, gsMatrix<real_t>& x, const gsMatrix<real_t>& f)
{
    dampedRichardsonSweep(A, x, f, m_damping);
}

void gsJacobiSmoother::apply(const Eigen::SparseMatrix<real_t>& A, gsMatrix<real_t>& x, const gsMatrix<real_t>& f)
{
    dampedJacobiSweep(A, x, f, m_damping);
}

void gsGaussSeidelSmoother::apply(const Eigen::SparseMatrix<real_t>& A, gsMatrix<real_t>& x, const gsMatrix<real_t>& f)
{
    gaussSeidelSweep(A, x, f);
}

void gsGaussSeidelSmoother::applyT(const Eigen::SparseMatrix<real_t>& A, gsMatrix<real_t>& x, const gsMatrix<real_t>& f)
{
    reverseGaussSeidelSweep(A, x, f);
}

void gsGaussSeidelBlockSmoother::apply(const Eigen::SparseMatrix<real_t>& A, gsMatrix<real_t>& x, const gsMatrix<real_t>& f)
{
    assert( A.rows() == x.rows() && x.rows() == f.rows() );
    assert( A.cols() == A.rows() && x.cols() == 1 && f.cols() == 1);
    assert( m_blockInfo.size() > 0);

    const index_t numberOfBlocks = m_blockInfo.size();
    for (index_t k = 0; k < numberOfBlocks; k++)
        gaussSeidelSingleBlock(A, x, f, m_blockInfo[k]);
}

void gsGaussSeidelBlockSmoother::applyT(const Eigen::SparseMatrix<real_t>& A, gsMatrix<real_t>& x, const gsMatrix<real_t>& f)
{
    assert( A.rows() == x.rows() && x.rows() == f.rows() );
    assert( A.cols() == A.rows() && x.cols() == 1 && f.cols() == 1);
    assert( m_blockInfo.size() > 0);

    const index_t numberOfBlocks = m_blockInfo.size();
    for (index_t k = 0; k < numberOfBlocks; k++)
        gaussSeidelSingleBlock(A, x, f, m_blockInfo[numberOfBlocks - 1 - k]);
}

gsILUTSmoother::gsILUTSmoother(const Eigen::SparseMatrix<real_t>& K)
{
    m_ilu.setFillfactor(1);
    m_ilu.compute(K);
}

void gsILUTSmoother::apply(const Eigen::SparseMatrix<real_t>& A, gsMatrix<real_t>& x, const gsMatrix<real_t>& f)
{
    x += m_ilu.solve( f - A * x ).eval();
}

} // namespace gismo

<commit_msg>Fixed block smoother, dofs no longer have to be chronological<commit_after>/** @file gsSmoother.cpp

    @brief Provides Multigrid smoothers.

    This file is part of the G+Smo library.

    This Source Code Form is subject to the terms of the Mozilla Public
    License, v. 2.0. If a copy of the MPL was not distributed with this
    file, You can obtain one at http://mozilla.org/MPL/2.0/.

    Author(s): C. Hofreither
*/
#include <gsSolver/gsSmoother.h>
#include <gsCore/gsLinearAlgebra.h>

namespace gismo
{

// smoothers

void dampedRichardsonSweep(const Eigen::SparseMatrix<real_t>& A, gsMatrix<real_t>& x, const gsMatrix<real_t>& f, real_t tau = (real_t)(1))
{
    assert( A.rows() == x.rows() && x.rows() == f.rows() );
    assert( A.cols() == A.rows() && x.cols() == 1 && f.cols() == 1);

    gsMatrix<real_t> temp = f - A * x;
    x += tau * temp;
}

void dampedRichardsonSweepBoundary(const Eigen::SparseMatrix<real_t>& A, gsMatrix<real_t>& x, const gsMatrix<real_t>& f, real_t tau, int numBdNodes)
{
    assert( A.rows() == x.rows() && x.rows() == f.rows() );
    assert( A.cols() == A.rows() && x.cols() == 1 && f.cols() == 1);

    gsMatrix<real_t> temp = f - A * x;
    for (int i = 0; i < A.outerSize(); ++i)
    {
        if (i < numBdNodes || i >= A.outerSize() - numBdNodes)
            x(i) += tau * temp(i);
    }
}

// assumes symmetric matrix
void kaczmarzSweepBoundary(const Eigen::SparseMatrix<real_t>& A, gsMatrix<real_t>& x, const gsMatrix<real_t>& f, real_t tau, int numBdNodes)
{
    assert( A.rows() == x.rows() && x.rows() == f.rows() );
    assert( A.cols() == A.rows() && x.cols() == 1 && f.cols() == 1);

    for (int eq = 0; eq < A.outerSize(); ++eq)
    {
        if (!(eq < numBdNodes || eq >= A.outerSize() - numBdNodes))
            continue;

        real_t Asq = 0;
        real_t Aeqx = 0;

        for (Eigen::SparseMatrix<real_t>::InnerIterator it(A,eq); it; ++it)
        {
            Asq += it.value() * it.value();         // compute squared norm of A_eq
            Aeqx += it.value() * x(it.index());     // compute A_eq . x
        }

        const real_t beta = (f(eq) - Aeqx) / Asq;

        for (Eigen::SparseMatrix<real_t>::InnerIterator it(A,eq); it; ++it)
        {
            x(it.index()) += beta * it.value();     // add beta * A_eq
        }
    }
}

void jacobiSweep(const Eigen::SparseMatrix<real_t>& A, gsMatrix<real_t>& x, const gsMatrix<real_t>& f)
{
    assert( A.rows() == x.rows() && x.rows() == f.rows() );
    assert( A.cols() == A.rows() && x.cols() == 1 && f.cols() == 1);

    gsMatrix<real_t> temp = f - A * x;
    temp.array() /= A.diagonal().array();
    x += temp;
}

void dampedJacobiSweep(const Eigen::SparseMatrix<real_t>& A, gsMatrix<real_t>& x, const gsMatrix<real_t>& f, real_t tau = (real_t)(1.0/2.0))
{
    assert( A.rows() == x.rows() && x.rows() == f.rows() );
    assert( A.cols() == A.rows() && x.cols() == 1 && f.cols() == 1);

    gsMatrix<real_t> temp = f - A * x;
    temp.array() /= A.diagonal().array();
    x += tau * temp;
}

void dampedPreRichardsonSweep(const Eigen::SparseMatrix<real_t>& A, const Eigen::SparseMatrix<real_t>& P, gsMatrix<real_t>& x, const gsMatrix<real_t>& f, real_t tau)
{
    assert( A.rows() == x.rows() && x.rows() == f.rows() );
    assert( A.cols() == A.rows() && x.cols() == 1 && f.cols() == 1);

    gsSparseSolver<>::CGDiagonal solver;
    gsMatrix<real_t> corr;
    corr = f - A * x;
    corr = solver.compute( P ).setTolerance(1e-3).solve(corr).eval();
    //corr.array() *= P.diagonal().array();
    x += tau * corr;
}

void dampedPreJacobiSweep(const Eigen::SparseMatrix<real_t>& A, const Eigen::SparseMatrix<real_t>& P, gsMatrix<real_t>& x, const gsMatrix<real_t>& f, real_t tau = (real_t)(1.0/2.0))
{
    assert( A.rows() == x.rows() && x.rows() == f.rows() );
    assert( A.cols() == A.rows() && x.cols() == 1 && f.cols() == 1);

    //gsMatrix<real_t> temp = f - A * x;
    //temp.array() /= A.diagonal().array();
    //x = tau * temp;

#if 0
    // original version
    gsMatrix<real_t> corr;
    corr = f - A * x;
    corr.array() /= A.diagonal().array();

    corr = gsSparseSolver<>::CGDiagonal( P ).setTolerance(1e-3).solve(corr).eval();
    corr.array() *= P.diagonal().array();
#else
    // symmetricized version
    gsMatrix<real_t> corr;
    corr = f - A * x;

    corr.array() /= A.diagonal().array().sqrt();
    corr.array() *= P.diagonal().array().sqrt();

    corr = gsSparseSolver<>::CGDiagonal( P ).setTolerance(1e-3).solve(corr).eval();

    corr.array() *= P.diagonal().array().sqrt();
    corr.array() /= A.diagonal().array().sqrt();
#endif

    x += tau * corr;
}

void gaussSeidelSweep(const Eigen::SparseMatrix<real_t>& A, gsMatrix<real_t>& x, const gsMatrix<real_t>& f)
{
    assert( A.rows() == x.rows() && x.rows() == f.rows() );
    assert( A.cols() == A.rows() && x.cols() == 1 && f.cols() == 1);

    // A is supposed to be symmetric, so it doesn't matter if it's stored in row- or column-major order
    for (int i = 0; i < A.outerSize(); ++i)
    {
        real_t diag = real_t(0.0);
        real_t sum = real_t(0.0);

        for (Eigen::SparseMatrix<real_t>::InnerIterator it(A,i); it; ++it)
        {
            sum += it.value() * x( it.index() );        // compute A.x
            if (it.index() == i)
                diag = it.value();
        }

        x(i) += (f(i) - sum) / diag;
    }
}

void reverseGaussSeidelSweep(const Eigen::SparseMatrix<real_t>& A, gsMatrix<real_t>& x, const gsMatrix<real_t>& f)
{
    assert( A.rows() == x.rows() && x.rows() == f.rows() );
    assert( A.cols() == A.rows() && x.cols() == 1 && f.cols() == 1);

    // A is supposed to be symmetric, so it doesn't matter if it's stored in row- or column-major order
    for (int i = A.outerSize() - 1; i >= 0; --i)
    {
        real_t diag = real_t(0.0);
        real_t sum = real_t(0.0);

        for (Eigen::SparseMatrix<real_t>::InnerIterator it(A,i); it; ++it)
        {
            sum += it.value() * x( it.index() );        // compute A.x
            if (it.index() == i)
                diag = it.value();
        }

        x(i) += (f(i) - sum) / diag;
    }
}

void gaussSeidelSingleBlock(const Eigen::SparseMatrix<real_t>& A, gsMatrix<real_t>& x, const gsMatrix<real_t>& f, gsVector<index_t>& DoFs)
{
    //Sorting from lowest to highest
    DoFs.sortByColumn(0);
    const index_t size = DoFs.rows();

    GISMO_ASSERT ( DoFs(size-1)< A.cols(), "The given DoF is higher than the size of the matrix");

    gsMatrix<real_t> Dblock(size, size);
    gsMatrix<real_t> residual(size, 1);
    for (int i = 0; i< size; i++)
    {
        residual(i,0) = f(DoFs(i),0) - (A.block(DoFs(i), 0, 1, A.cols())*x).value();
        for (int j = 0; j< size; j++)
            Dblock(i,j) = A.coeff(DoFs(i), DoFs(j));
    }
    //Multiply residual with the inverse of the diagonal block
    residual = Dblock.inverse()*residual;

    //Update
    for (int i = 0; i< size; i++)
       x(DoFs(i),0) += residual(i,0);
}

void preGaussSeidelSweep(const Eigen::SparseMatrix<real_t>& A, const Eigen::SparseMatrix<real_t>& P, gsMatrix<real_t>& x, const gsMatrix<real_t>& f, real_t tau, bool reverse)
{
    assert( A.rows() == x.rows() && x.rows() == f.rows() );
    assert( A.cols() == A.rows() && x.cols() == 1 && f.cols() == 1);

    gsMatrix<real_t> corr;
    corr.setZero( x.rows(), 1 );

    //const int start_i = reverse ? A.outerSize() - 1 : 0                 ;
    //const int end_i   = reverse ? 0                 : A.outerSize() - 1 ;
    //const int inc_i   = reverse ? -1                : 1                 ;

    // A is supposed to be symmetric, so it doesn't matter if it's stored in row- or column-major order
    for (int i = 0; i < A.outerSize(); ++i)
    {
        real_t diag = real_t(0.0);
        real_t sum = real_t(0.0);

        for (Eigen::SparseMatrix<real_t>::InnerIterator it(A,i); it; ++it)
        {
            sum += it.value() * (x( it.index() ) + corr( it.index() ));        // compute A.x
            if (it.index() == i)
                diag = it.value();
        }

        corr(i) = (f(i) - sum) / diag;
    }

    corr = gsSparseSolver<>::CGDiagonal( P )
            .setTolerance(1e-3).solve(corr).eval();
    x.array() += tau * /*P.diagonal().array() * */ corr.array();
}

////////////////////////////////////////////////////////////////////////////////
// smoother class implementations
////////////////////////////////////////////////////////////////////////////////

void gsRichardsonSmoother::apply(const Eigen::SparseMatrix<real_t>& A, gsMatrix<real_t>& x, const gsMatrix<real_t>& f)
{
    dampedRichardsonSweep(A, x, f, m_damping);
}

void gsJacobiSmoother::apply(const Eigen::SparseMatrix<real_t>& A, gsMatrix<real_t>& x, const gsMatrix<real_t>& f)
{
    dampedJacobiSweep(A, x, f, m_damping);
}

void gsGaussSeidelSmoother::apply(const Eigen::SparseMatrix<real_t>& A, gsMatrix<real_t>& x, const gsMatrix<real_t>& f)
{
    gaussSeidelSweep(A, x, f);
}

void gsGaussSeidelSmoother::applyT(const Eigen::SparseMatrix<real_t>& A, gsMatrix<real_t>& x, const gsMatrix<real_t>& f)
{
    reverseGaussSeidelSweep(A, x, f);
}

void gsGaussSeidelBlockSmoother::apply(const Eigen::SparseMatrix<real_t>& A, gsMatrix<real_t>& x, const gsMatrix<real_t>& f)
{
    assert( A.rows() == x.rows() && x.rows() == f.rows() );
    assert( A.cols() == A.rows() && x.cols() == 1 && f.cols() == 1);
    assert( m_blockInfo.size() > 0);

    const index_t numberOfBlocks = m_blockInfo.size();
    for (index_t k = 0; k < numberOfBlocks; k++)
        gaussSeidelSingleBlock(A, x, f, m_blockInfo[k]);
}

void gsGaussSeidelBlockSmoother::applyT(const Eigen::SparseMatrix<real_t>& A, gsMatrix<real_t>& x, const gsMatrix<real_t>& f)
{
    assert( A.rows() == x.rows() && x.rows() == f.rows() );
    assert( A.cols() == A.rows() && x.cols() == 1 && f.cols() == 1);
    assert( m_blockInfo.size() > 0);

    const index_t numberOfBlocks = m_blockInfo.size();
    for (index_t k = 0; k < numberOfBlocks; k++)
        gaussSeidelSingleBlock(A, x, f, m_blockInfo[numberOfBlocks - 1 - k]);
}

gsILUTSmoother::gsILUTSmoother(const Eigen::SparseMatrix<real_t>& K)
{
    m_ilu.setFillfactor(1);
    m_ilu.compute(K);
}

void gsILUTSmoother::apply(const Eigen::SparseMatrix<real_t>& A, gsMatrix<real_t>& x, const gsMatrix<real_t>& f)
{
    x += m_ilu.solve( f - A * x ).eval();
}

} // namespace gismo

<|endoftext|>


<commit_before>/****************************************************************************
 **
 ** Copyright (C) Qxt Foundation. Some rights reserved.
 **
 ** This file is part of the QxtGui module of the Qxt library.
 **
 ** This library is free software; you can redistribute it and/or modify it
 ** under the terms of the Common Public License, version 1.0, as published
 ** by IBM, and/or under the terms of the GNU Lesser General Public License,
 ** version 2.1, as published by the Free Software Foundation.
 **
 ** This file is provided "AS IS", without WARRANTIES OR CONDITIONS OF ANY
 ** KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY
 ** WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR
 ** FITNESS FOR A PARTICULAR PURPOSE.
 **
 ** You should have received a copy of the CPL and the LGPL along with this
 ** file. See the LICENSE file and the cpl1.0.txt/lgpl-2.1.txt files
 ** included with the source distribution for more information.
 ** If you did not receive a copy of the licenses, contact the Qxt Foundation.
 **
 ** <http://libqxt.org>  <foundation@libqxt.org>
 **
 ****************************************************************************/

#include "qxtcountrymodel.h"
#include "qxtcountrymodel_p.h"
#include "qxtlocale.h"
#include <QIcon>
#include <QLocale>
#include <QDebug>
#include <QApplication>
#if QT_VERSION >= 0x040300
#include <QMetaEnum>
#endif

class QxtCountry;
typedef QList<QxtCountry> QxtCountryList;

class QxtCountry
{
public:
    explicit QxtCountry(QLocale::Country country)
            : _mCountry(country)
    {
        _mName = qApp->translate("QLocale", qPrintable(QLocale::countryToString(_mCountry)));
        _mCurrency = QxtLocale::currencyForCountry(_mCountry);
    }

    const QString& name() const
    {
        return _mName;
    }
    QLocale::Country country() const
    {
        return _mCountry;
    }
    QxtLocale::Currency currency() const
    {
        return _mCurrency;
    }

    bool operator<(const QxtCountry& country) const
    {
        return _mName.localeAwareCompare(country._mName) < 0;
    }

    static const QxtCountryList& loadCountries()
    {
        if (!_smCountryNames.empty())
            return _smCountryNames;

        for (int idx = 0; idx < QLocale::LastCountry; ++idx)
        {
            QLocale::Country c = static_cast<QLocale::Country>(idx);
            if (c == QLocale::LastCountry)
                continue;
            if (c == QLocale::AnyCountry)
                continue;

            _smCountryNames.push_back(QxtCountry(c));
        }

        qSort(_smCountryNames);
        return _smCountryNames;
    }

private:
    QString             _mName;
    QLocale::Country    _mCountry;
    QxtLocale::Currency _mCurrency;

private:
    static QxtCountryList _smCountryNames;
};

QxtCountryList QxtCountry::_smCountryNames;

QxtCountryModelPrivate::QxtCountryModelPrivate()
{
}

int QxtCountryModelPrivate::rowCount(const QModelIndex&) const
{
    return QxtCountry::loadCountries().size();
}

int QxtCountryModelPrivate::columnCount(const QModelIndex&) const
{
    return 8;
}

QVariant QxtCountryModelPrivate::data(const QModelIndex& index, int role) const
{
    if (!index.isValid())
        return QVariant();

    const QxtCountry& c = QxtCountry::loadCountries().operator[](index.row());
    if (role == Qt::DecorationRole && index.column() == 0)
        return QIcon(":/flags/" + QxtLocale::countryToISO2Letter(c.country()) + ".png");

    if (role == Qt::DisplayRole)
    {
        switch (index.column())
        {
        case 0:
            return c.name();
        case 1:
            return QxtLocale::countryToISO2Letter(c.country());
        case 2:
            return c.country();
        case 3:
            return QxtLocale::countryToISO3Letter(c.country());
        case 4:
            return QxtLocale::currencyToName(c.currency());
        case 5:
            return QxtLocale::currencyToCode(c.currency());
        case 6:
            return QxtLocale::currencyToSymbol(c.currency());
        case 7:
            return QxtLocale::continentToName(QxtLocale::continentForCountry(c.country()));
        default:
            return QVariant();
        }
    }
    return QVariant();
}

/*!
    \class QxtCountryModel QxtCountryModel
    \inmodule QxtGui
    \brief A subclass of QAbstractTableModel to display country data.

    QxtCountryModel is a specialized QAbstractTableModel to display countries.
    The countries are taken from QLocale::Country.

    \image qxtcountrymodel.png "QxtCountryModel in a QTableView in Plastique style."
 */

QxtCountryModel::QxtCountryModel(QObject* parent)
        : QAbstractTableModel(parent)
{
    QXT_INIT_PRIVATE(QxtCountryModel);
}

QxtCountryModel::~QxtCountryModel()
{
}

/*!
    \fn QxtCountryModel::rowCount(const QModelIndex& parent)

    Returns the number of rows in the model.
 */
int QxtCountryModel::rowCount(const QModelIndex& parent) const
{
    return qxt_d().rowCount(parent);
}

/*!
    \fn QxtCountryModel::columnCount(const QModelIndex& parent)

    Returns the number of columns in the model.
 */
int QxtCountryModel::columnCount(const QModelIndex& parent) const
{
    return qxt_d().columnCount(parent);
}

/*!
    \fn QxtCountryModel::data(const QModelIndex& index, int role)

    Returns the data for the given \a index for a sepcific role.
 */
QVariant QxtCountryModel::data(const QModelIndex& index, int role) const
{
    return qxt_d().data(index, role);
}

/*!
    \fn QxtCountryModel::headerData(int section, Qt::Orientation orientation, int role)

    Returns the column or row name for the given \a section for a sepcific role.
 */
QVariant QxtCountryModel::headerData(int section, Qt::Orientation orientation, int role) const
{
    if (orientation == Qt::Horizontal && role == Qt::DisplayRole)
    {
        switch (section)
        {
        case 0:
            return tr("Name");
        case 1:
            return tr("ISO 3166 Alpha 2");
        case 2:
            return tr("QLocale");
        case 3:
            return tr("ISO 3166 Alpha 3");
        case 4:
            return tr("Currency");
        case 5:
            return tr("Currency Code");
        case 6:
            return tr("Currency Symbol");
        case 7:
            return tr("Continent");
        }
    }

    return QAbstractTableModel::headerData(section, orientation, role);
}

<commit_msg>Fixed QxtCountryModel docs.<commit_after>/****************************************************************************
 **
 ** Copyright (C) Qxt Foundation. Some rights reserved.
 **
 ** This file is part of the QxtGui module of the Qxt library.
 **
 ** This library is free software; you can redistribute it and/or modify it
 ** under the terms of the Common Public License, version 1.0, as published
 ** by IBM, and/or under the terms of the GNU Lesser General Public License,
 ** version 2.1, as published by the Free Software Foundation.
 **
 ** This file is provided "AS IS", without WARRANTIES OR CONDITIONS OF ANY
 ** KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY
 ** WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR
 ** FITNESS FOR A PARTICULAR PURPOSE.
 **
 ** You should have received a copy of the CPL and the LGPL along with this
 ** file. See the LICENSE file and the cpl1.0.txt/lgpl-2.1.txt files
 ** included with the source distribution for more information.
 ** If you did not receive a copy of the licenses, contact the Qxt Foundation.
 **
 ** <http://libqxt.org>  <foundation@libqxt.org>
 **
 ****************************************************************************/

#include "qxtcountrymodel.h"
#include "qxtcountrymodel_p.h"
#include "qxtlocale.h"
#include <QIcon>
#include <QLocale>
#include <QDebug>
#include <QApplication>
#if QT_VERSION >= 0x040300
#include <QMetaEnum>
#endif

class QxtCountry;
typedef QList<QxtCountry> QxtCountryList;

class QxtCountry
{
public:
    explicit QxtCountry(QLocale::Country country)
            : _mCountry(country)
    {
        _mName = qApp->translate("QLocale", qPrintable(QLocale::countryToString(_mCountry)));
        _mCurrency = QxtLocale::currencyForCountry(_mCountry);
    }

    const QString& name() const
    {
        return _mName;
    }
    QLocale::Country country() const
    {
        return _mCountry;
    }
    QxtLocale::Currency currency() const
    {
        return _mCurrency;
    }

    bool operator<(const QxtCountry& country) const
    {
        return _mName.localeAwareCompare(country._mName) < 0;
    }

    static const QxtCountryList& loadCountries()
    {
        if (!_smCountryNames.empty())
            return _smCountryNames;

        for (int idx = 0; idx < QLocale::LastCountry; ++idx)
        {
            QLocale::Country c = static_cast<QLocale::Country>(idx);
            if (c == QLocale::LastCountry)
                continue;
            if (c == QLocale::AnyCountry)
                continue;

            _smCountryNames.push_back(QxtCountry(c));
        }

        qSort(_smCountryNames);
        return _smCountryNames;
    }

private:
    QString             _mName;
    QLocale::Country    _mCountry;
    QxtLocale::Currency _mCurrency;

private:
    static QxtCountryList _smCountryNames;
};

QxtCountryList QxtCountry::_smCountryNames;

QxtCountryModelPrivate::QxtCountryModelPrivate()
{
}

int QxtCountryModelPrivate::rowCount(const QModelIndex&) const
{
    return QxtCountry::loadCountries().size();
}

int QxtCountryModelPrivate::columnCount(const QModelIndex&) const
{
    return 8;
}

QVariant QxtCountryModelPrivate::data(const QModelIndex& index, int role) const
{
    if (!index.isValid())
        return QVariant();

    const QxtCountry& c = QxtCountry::loadCountries().operator[](index.row());
    if (role == Qt::DecorationRole && index.column() == 0)
        return QIcon(":/flags/" + QxtLocale::countryToISO2Letter(c.country()) + ".png");

    if (role == Qt::DisplayRole)
    {
        switch (index.column())
        {
        case 0:
            return c.name();
        case 1:
            return QxtLocale::countryToISO2Letter(c.country());
        case 2:
            return c.country();
        case 3:
            return QxtLocale::countryToISO3Letter(c.country());
        case 4:
            return QxtLocale::currencyToName(c.currency());
        case 5:
            return QxtLocale::currencyToCode(c.currency());
        case 6:
            return QxtLocale::currencyToSymbol(c.currency());
        case 7:
            return QxtLocale::continentToName(QxtLocale::continentForCountry(c.country()));
        default:
            return QVariant();
        }
    }
    return QVariant();
}

/*!
    \class QxtCountryModel QxtCountryModel
    \inmodule QxtGui
    \brief A subclass of QAbstractTableModel to display country data.

    QxtCountryModel is a specialized QAbstractTableModel to display countries.
    The countries are taken from QLocale::Country.

    \image qxtcountrymodel.png "QxtCountryModel in a QTableView in Plastique style."
 */

QxtCountryModel::QxtCountryModel(QObject* parent)
        : QAbstractTableModel(parent)
{
    QXT_INIT_PRIVATE(QxtCountryModel);
}

QxtCountryModel::~QxtCountryModel()
{
}

/*!
    \fn QxtCountryModel::rowCount(const QModelIndex& parent) const

    Returns the number of rows in the model.
 */
int QxtCountryModel::rowCount(const QModelIndex& parent) const
{
    return qxt_d().rowCount(parent);
}

/*!
    \fn QxtCountryModel::columnCount(const QModelIndex& parent) const

    Returns the number of columns in the model.
 */
int QxtCountryModel::columnCount(const QModelIndex& parent) const
{
    return qxt_d().columnCount(parent);
}

/*!
    \fn QxtCountryModel::data(const QModelIndex& index, int role) const

    Returns the data for the given \a index for a sepcific role.
 */
QVariant QxtCountryModel::data(const QModelIndex& index, int role) const
{
    return qxt_d().data(index, role);
}

/*!
    \fn QxtCountryModel::headerData(int section, Qt::Orientation orientation, int role) const

    Returns the column or row name for the given \a section for a sepcific role.
 */
QVariant QxtCountryModel::headerData(int section, Qt::Orientation orientation, int role) const
{
    if (orientation == Qt::Horizontal && role == Qt::DisplayRole)
    {
        switch (section)
        {
        case 0:
            return tr("Name");
        case 1:
            return tr("ISO 3166 Alpha 2");
        case 2:
            return tr("QLocale");
        case 3:
            return tr("ISO 3166 Alpha 3");
        case 4:
            return tr("Currency");
        case 5:
            return tr("Currency Code");
        case 6:
            return tr("Currency Symbol");
        case 7:
            return tr("Continent");
        }
    }

    return QAbstractTableModel::headerData(section, orientation, role);
}

<|endoftext|>


<commit_before>#include <stdio.h>
#include <memory>

#include <SFGUI/Button.hpp>
#include <SFGUI/Label.hpp>
#include <SFGUI/Table.hpp>
#include <SFGUI/SpinButton.hpp>
#include <SFGUI/Image.hpp>

#include "gui/startgamewindow.hpp"
#include "gui/imagemanager.hpp"
#include "gui/cursor.hpp"
#include "engine/unit.hpp"

namespace qrw
{
	StartGameWindow::Ptr StartGameWindow::Create(Engine* engine,
		IngameWindow* ingamewindow, DeployWindow* deploywindow,
		BoardWidget* boardwidget, GuiHandler* guihandler)
	{
		Ptr window(new StartGameWindow(engine, ingamewindow,
			deploywindow, boardwidget, guihandler));
		window->SetTitle("Start new game");

		ImageManager* imgmgr = ImageManager::getInstance();

		sfg::Image::Ptr swordsmanimg = sfg::Image::Create(
			*imgmgr->getImage("p1swordman"));
		sfg::Image::Ptr archerimg = sfg::Image::Create(
			*imgmgr->getImage("p1archer"));
		sfg::Image::Ptr spearmanimg = sfg::Image::Create(
			*imgmgr->getImage("p1spearman"));

		sfg::Label::Ptr playeronelabel = sfg::Label::Create("Player 1");
		sfg::Label::Ptr playertwolabel = sfg::Label::Create("Player 2");

		sfg::SpinButton::Ptr p1swordspin = sfg::SpinButton::Create(0, 100, 1);
		p1swordspin->SetValue(0);
		p1swordspin->SetId("p1swordspin");
		sfg::SpinButton::Ptr p1archspin  = sfg::SpinButton::Create(0, 100, 1);
		p1archspin->SetValue(0);
		p1archspin->SetId("p1archspin");
		sfg::SpinButton::Ptr p1spearspin = sfg::SpinButton::Create(0, 100, 1);
		p1spearspin->SetValue(0);
		p1spearspin->SetId("p1spearspin");
		sfg::SpinButton::Ptr p2swordspin = sfg::SpinButton::Create(0, 100, 1);
		p2swordspin->SetValue(0);
		p2swordspin->SetId("p2swordspin");
		sfg::SpinButton::Ptr p2archspin  = sfg::SpinButton::Create(0, 100, 1);
		p2archspin->SetValue(0);
		p2archspin->SetId("p2archspin");
		sfg::SpinButton::Ptr p2spearspin = sfg::SpinButton::Create(0, 100, 1);
		p2spearspin->SetValue(0);
		p2spearspin->SetId("p2spearspin");

		sfg::Label::Ptr boardwidthlabel = sfg::Label::Create("Board X");
		sfg::Label::Ptr boardheightlabel = sfg::Label::Create("Borad Y");

		sfg::SpinButton::Ptr boardwidthspin = sfg::SpinButton::Create(3, 20, 1);
		boardwidthspin->SetValue(3);
		boardwidthspin->SetId("boardwidthspin");
		sfg::SpinButton::Ptr boardheightspin = sfg::SpinButton::Create(3, 20, 1);
		boardheightspin->SetValue(3);
		boardheightspin->SetId("boardheightspin");

		sfg::Button::Ptr closebutton = sfg::Button::Create("Close");
		closebutton->GetSignal(sfg::Button::OnLeftClick).Connect(
			std::bind(&StartGameWindow::hide, window));
		sfg::Button::Ptr startbutton = sfg::Button::Create("Start game");
		startbutton->GetSignal(sfg::Button::OnLeftClick).Connect(
			std::bind(&StartGameWindow::startGame, window));

		sfg::Table::Ptr maincontainer = sfg::Table::Create();
		int options = sfg::Table::FILL | sfg::Table::EXPAND;
		// Images
		maincontainer->Attach(swordsmanimg, sf::Rect<sf::Uint32>(0, 1, 1, 1));
		maincontainer->Attach(archerimg, sf::Rect<sf::Uint32>(0, 2, 1, 1));
		maincontainer->Attach(spearmanimg, sf::Rect<sf::Uint32>(0, 3, 1, 1));
		// Player 1 stuff
		maincontainer->Attach(playeronelabel, sf::Rect<sf::Uint32>(1, 0, 1, 1), options, options);
		maincontainer->Attach(p1swordspin, sf::Rect<sf::Uint32>(1, 1, 1, 1), options, options);
		maincontainer->Attach(p1archspin, sf::Rect<sf::Uint32>(1, 2, 1, 1), options, options);
		maincontainer->Attach(p1spearspin, sf::Rect<sf::Uint32>(1, 3, 1, 1), options, options);
		// Player 2 stuff
		maincontainer->Attach(playertwolabel, sf::Rect<sf::Uint32>(2, 0, 1, 1), options, options);
		maincontainer->Attach(p2swordspin, sf::Rect<sf::Uint32>(2, 1, 1, 1), options, options);
		maincontainer->Attach(p2archspin, sf::Rect<sf::Uint32>(2, 2, 1, 1), options, options);
		maincontainer->Attach(p2spearspin, sf::Rect<sf::Uint32>(2, 3, 1, 1), options, options);
		// Board settings
		maincontainer->Attach(boardwidthlabel, sf::Rect<sf::Uint32>(1, 4, 1, 1), options, options);
		maincontainer->Attach(boardheightlabel, sf::Rect<sf::Uint32>(2, 4, 1, 1), options, options);
		maincontainer->Attach(boardwidthspin, sf::Rect<sf::Uint32>(1, 5, 1, 1), options, options);
		maincontainer->Attach(boardheightspin, sf::Rect<sf::Uint32>(2, 5, 1, 1), options, options);
		// Buttons
		maincontainer->Attach(closebutton, sf::Rect<sf::Uint32>(0, 6, 2, 1), options, options);
		maincontainer->Attach(startbutton, sf::Rect<sf::Uint32>(2, 6, 1, 1), options, options);

		window->Add(maincontainer);
		window->SetAllocation(sf::FloatRect(200, 0, 350, 100));
		window->Show(false);
		return window;
	}

	StartGameWindow::StartGameWindow(Engine* engine, IngameWindow* ingamewindow,
		DeployWindow* deploywindow, BoardWidget* boardwidget,
		GuiHandler* guihandler, int style)
	: Window(style),
	  engine(engine),
	  guihandler(guihandler),
	  ingamewindow(ingamewindow),
	  deploywindow(deploywindow),
	  boardwidget(boardwidget)
	{}

	void StartGameWindow::startGame()
	{
		// Init engine
		int width = std::static_pointer_cast<sfg::SpinButton>(sfg::Widget::GetWidgetById("boardwidthspin"))->GetValue();
		int height = std::static_pointer_cast<sfg::SpinButton>(sfg::Widget::GetWidgetById("boardheightspin"))->GetValue();
		engine->init(width, height);

		// Create unit arrays for engine.
		std::map<UNITTYPES, int> unitcounts;

		// Set unit counts for player one.
		unitcounts[EUT_SWORDMAN] = std::static_pointer_cast<sfg::SpinButton>(sfg::Widget::GetWidgetById("p1swordspin"))->GetValue();
		unitcounts[EUT_ARCHER] = std::static_pointer_cast<sfg::SpinButton>(sfg::Widget::GetWidgetById("p1archspin"))->GetValue();
		unitcounts[EUT_SPEARMAN] = std::static_pointer_cast<sfg::SpinButton>(sfg::Widget::GetWidgetById("p1spearspin"))->GetValue();
		engine->createPlayerUnits(0, unitcounts);

		// Set unit counts for player two.
		unitcounts[EUT_SWORDMAN] = std::static_pointer_cast<sfg::SpinButton>(sfg::Widget::GetWidgetById("p2swordspin"))->GetValue();
		unitcounts[EUT_ARCHER] = std::static_pointer_cast<sfg::SpinButton>(sfg::Widget::GetWidgetById("p2archspin"))->GetValue();
		unitcounts[EUT_SPEARMAN] = std::static_pointer_cast<sfg::SpinButton>(sfg::Widget::GetWidgetById("p2spearspin"))->GetValue();
		engine->createPlayerUnits(1, unitcounts);

		boardwidget->setBoard(engine->getBoard());
		Cursor::getCursor()->setBoard(engine->getBoard());
		ingamewindow->update();
		ingamewindow->setVisible(false);
		deploywindow->update();
		deploywindow->setVisible(true);
		guihandler->toggleGui();
		hide();
	}

	void StartGameWindow::hide()
	{
		Show(false);
	}
}<commit_msg>Added sfg::Separator between unit and board set up in StartGameWindow.<commit_after>#include <stdio.h>
#include <memory>

#include <SFGUI/Button.hpp>
#include <SFGUI/Label.hpp>
#include <SFGUI/Table.hpp>
#include <SFGUI/SpinButton.hpp>
#include <SFGUI/Image.hpp>

#include "gui/startgamewindow.hpp"
#include "gui/imagemanager.hpp"
#include "gui/cursor.hpp"
#include "engine/unit.hpp"

namespace qrw
{
	StartGameWindow::Ptr StartGameWindow::Create(Engine* engine,
		IngameWindow* ingamewindow, DeployWindow* deploywindow,
		BoardWidget* boardwidget, GuiHandler* guihandler)
	{
		Ptr window(new StartGameWindow(engine, ingamewindow,
			deploywindow, boardwidget, guihandler));
		window->SetTitle("Start new game");

		ImageManager* imgmgr = ImageManager::getInstance();

		sfg::Image::Ptr swordsmanimg = sfg::Image::Create(
			*imgmgr->getImage("p1swordman"));
		sfg::Image::Ptr archerimg = sfg::Image::Create(
			*imgmgr->getImage("p1archer"));
		sfg::Image::Ptr spearmanimg = sfg::Image::Create(
			*imgmgr->getImage("p1spearman"));

		sfg::Label::Ptr playeronelabel = sfg::Label::Create("Player 1");
		sfg::Label::Ptr playertwolabel = sfg::Label::Create("Player 2");

		sfg::SpinButton::Ptr p1swordspin = sfg::SpinButton::Create(0, 100, 1);
		p1swordspin->SetValue(0);
		p1swordspin->SetId("p1swordspin");
		sfg::SpinButton::Ptr p1archspin  = sfg::SpinButton::Create(0, 100, 1);
		p1archspin->SetValue(0);
		p1archspin->SetId("p1archspin");
		sfg::SpinButton::Ptr p1spearspin = sfg::SpinButton::Create(0, 100, 1);
		p1spearspin->SetValue(0);
		p1spearspin->SetId("p1spearspin");
		sfg::SpinButton::Ptr p2swordspin = sfg::SpinButton::Create(0, 100, 1);
		p2swordspin->SetValue(0);
		p2swordspin->SetId("p2swordspin");
		sfg::SpinButton::Ptr p2archspin  = sfg::SpinButton::Create(0, 100, 1);
		p2archspin->SetValue(0);
		p2archspin->SetId("p2archspin");
		sfg::SpinButton::Ptr p2spearspin = sfg::SpinButton::Create(0, 100, 1);
		p2spearspin->SetValue(0);
		p2spearspin->SetId("p2spearspin");

		sfg::Separator::Ptr unitboardseparator = sfg::Separator::Create();

		sfg::Label::Ptr boardwidthlabel = sfg::Label::Create("Board X");
		sfg::Label::Ptr boardheightlabel = sfg::Label::Create("Borad Y");

		sfg::SpinButton::Ptr boardwidthspin = sfg::SpinButton::Create(3, 20, 1);
		boardwidthspin->SetValue(3);
		boardwidthspin->SetId("boardwidthspin");
		sfg::SpinButton::Ptr boardheightspin = sfg::SpinButton::Create(3, 20, 1);
		boardheightspin->SetValue(3);
		boardheightspin->SetId("boardheightspin");

		sfg::Button::Ptr closebutton = sfg::Button::Create("Close");
		closebutton->GetSignal(sfg::Button::OnLeftClick).Connect(
			std::bind(&StartGameWindow::hide, window));
		sfg::Button::Ptr startbutton = sfg::Button::Create("Start game");
		startbutton->GetSignal(sfg::Button::OnLeftClick).Connect(
			std::bind(&StartGameWindow::startGame, window));

		sfg::Table::Ptr maincontainer = sfg::Table::Create();
		int options = sfg::Table::FILL | sfg::Table::EXPAND;
		// Images
		maincontainer->Attach(swordsmanimg, sf::Rect<sf::Uint32>(0, 1, 1, 1));
		maincontainer->Attach(archerimg, sf::Rect<sf::Uint32>(0, 2, 1, 1));
		maincontainer->Attach(spearmanimg, sf::Rect<sf::Uint32>(0, 3, 1, 1));
		// Player 1 stuff
		maincontainer->Attach(playeronelabel, sf::Rect<sf::Uint32>(1, 0, 1, 1), options, options);
		maincontainer->Attach(p1swordspin, sf::Rect<sf::Uint32>(1, 1, 1, 1), options, options);
		maincontainer->Attach(p1archspin, sf::Rect<sf::Uint32>(1, 2, 1, 1), options, options);
		maincontainer->Attach(p1spearspin, sf::Rect<sf::Uint32>(1, 3, 1, 1), options, options);
		// Player 2 stuff
		maincontainer->Attach(playertwolabel, sf::Rect<sf::Uint32>(2, 0, 1, 1), options, options);
		maincontainer->Attach(p2swordspin, sf::Rect<sf::Uint32>(2, 1, 1, 1), options, options);
		maincontainer->Attach(p2archspin, sf::Rect<sf::Uint32>(2, 2, 1, 1), options, options);
		maincontainer->Attach(p2spearspin, sf::Rect<sf::Uint32>(2, 3, 1, 1), options, options);

		maincontainer->Attach(unitboardseparator, sf::Rect<sf::Uint32>(0, 5, 3, 1), options, options);

		// Board settings
		maincontainer->Attach(boardwidthlabel, sf::Rect<sf::Uint32>(1, 6, 1, 1), options, options);
		maincontainer->Attach(boardheightlabel, sf::Rect<sf::Uint32>(2, 6, 1, 1), options, options);
		maincontainer->Attach(boardwidthspin, sf::Rect<sf::Uint32>(1, 7, 1, 1), options, options);
		maincontainer->Attach(boardheightspin, sf::Rect<sf::Uint32>(2, 7, 1, 1), options, options);
		// Buttons
		maincontainer->Attach(closebutton, sf::Rect<sf::Uint32>(0, 8, 2, 1), options, options);
		maincontainer->Attach(startbutton, sf::Rect<sf::Uint32>(2, 8, 1, 1), options, options);

		window->Add(maincontainer);
		window->SetAllocation(sf::FloatRect(200, 0, 350, 100));
		window->Show(false);
		return window;
	}

	StartGameWindow::StartGameWindow(Engine* engine, IngameWindow* ingamewindow,
		DeployWindow* deploywindow, BoardWidget* boardwidget,
		GuiHandler* guihandler, int style)
	: Window(style),
	  engine(engine),
	  guihandler(guihandler),
	  ingamewindow(ingamewindow),
	  deploywindow(deploywindow),
	  boardwidget(boardwidget)
	{}

	void StartGameWindow::startGame()
	{
		// Init engine
		int width = std::static_pointer_cast<sfg::SpinButton>(sfg::Widget::GetWidgetById("boardwidthspin"))->GetValue();
		int height = std::static_pointer_cast<sfg::SpinButton>(sfg::Widget::GetWidgetById("boardheightspin"))->GetValue();
		engine->init(width, height);

		// Create unit arrays for engine.
		std::map<UNITTYPES, int> unitcounts;

		// Set unit counts for player one.
		unitcounts[EUT_SWORDMAN] = std::static_pointer_cast<sfg::SpinButton>(sfg::Widget::GetWidgetById("p1swordspin"))->GetValue();
		unitcounts[EUT_ARCHER] = std::static_pointer_cast<sfg::SpinButton>(sfg::Widget::GetWidgetById("p1archspin"))->GetValue();
		unitcounts[EUT_SPEARMAN] = std::static_pointer_cast<sfg::SpinButton>(sfg::Widget::GetWidgetById("p1spearspin"))->GetValue();
		engine->createPlayerUnits(0, unitcounts);

		// Set unit counts for player two.
		unitcounts[EUT_SWORDMAN] = std::static_pointer_cast<sfg::SpinButton>(sfg::Widget::GetWidgetById("p2swordspin"))->GetValue();
		unitcounts[EUT_ARCHER] = std::static_pointer_cast<sfg::SpinButton>(sfg::Widget::GetWidgetById("p2archspin"))->GetValue();
		unitcounts[EUT_SPEARMAN] = std::static_pointer_cast<sfg::SpinButton>(sfg::Widget::GetWidgetById("p2spearspin"))->GetValue();
		engine->createPlayerUnits(1, unitcounts);

		boardwidget->setBoard(engine->getBoard());
		Cursor::getCursor()->setBoard(engine->getBoard());
		ingamewindow->update();
		ingamewindow->setVisible(false);
		deploywindow->update();
		deploywindow->setVisible(true);
		guihandler->toggleGui();
		hide();
	}

	void StartGameWindow::hide()
	{
		Show(false);
	}
}<|endoftext|>


<commit_before>/*
 * nghttp2 - HTTP/2 C Library
 *
 * Copyright (c) 2014 Tatsuhiro Tsujikawa
 *
 * 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.
 */
#include "h2load_http2_session.h"

#include <cassert>

#include "h2load.h"
#include "util.h"

using namespace nghttp2;

namespace h2load {

Http2Session::Http2Session(Client *client)
  : client_(client),
    session_(nullptr)
{}

Http2Session::~Http2Session()
{
  nghttp2_session_del(session_);
}

namespace {
int before_frame_send_callback
(nghttp2_session *session, const nghttp2_frame *frame, void *user_data)
{
  auto client = static_cast<Client*>(user_data);
  if(frame->hd.type == NGHTTP2_HEADERS &&
     frame->headers.cat == NGHTTP2_HCAT_REQUEST) {
    client->on_request(frame->hd.stream_id);
  }
  return 0;
}
} // namespace

namespace {
int on_header_callback(nghttp2_session *session,
                       const nghttp2_frame *frame,
                       const uint8_t *name, size_t namelen,
                       const uint8_t *value, size_t valuelen,
                       uint8_t flags,
                       void *user_data)
{
  auto client = static_cast<Client*>(user_data);
  if(frame->hd.type != NGHTTP2_HEADERS ||
     frame->headers.cat != NGHTTP2_HCAT_RESPONSE) {
    return 0;
  }
  client->on_header(frame->hd.stream_id, name, namelen, value, valuelen);
  return 0;
}
} // namespace

namespace {
int on_frame_recv_callback(nghttp2_session *session,
                           const nghttp2_frame *frame,
                           void *user_data)
{
  auto client = static_cast<Client*>(user_data);
  if(frame->hd.type != NGHTTP2_HEADERS ||
     frame->headers.cat != NGHTTP2_HCAT_RESPONSE) {
    return 0;
  }
  client->worker->stats.bytes_head += frame->hd.length;
  return 0;
}
} // namespace

namespace {
int on_data_chunk_recv_callback
(nghttp2_session *session, uint8_t flags, int32_t stream_id,
 const uint8_t *data, size_t len, void *user_data)
{
  auto client = static_cast<Client*>(user_data);
  client->worker->stats.bytes_body += len;
  return 0;
}
} // namespace

namespace {
int on_stream_close_callback
(nghttp2_session *session, int32_t stream_id, nghttp2_error_code error_code,
 void *user_data)
{
  auto client = static_cast<Client*>(user_data);
  client->on_stream_close(stream_id, error_code == NGHTTP2_NO_ERROR);
  return 0;
}
} // namespace

void Http2Session::on_connect()
{
  int rv;

  nghttp2_session_callbacks callbacks = {0};
  callbacks.before_frame_send_callback = before_frame_send_callback;
  callbacks.on_frame_recv_callback = on_frame_recv_callback;
  callbacks.on_data_chunk_recv_callback = on_data_chunk_recv_callback;
  callbacks.on_stream_close_callback = on_stream_close_callback;
  callbacks.on_header_callback = on_header_callback;

  nghttp2_session_client_new(&session_, &callbacks, client_);

  nghttp2_settings_entry iv[2];
  iv[0].settings_id = NGHTTP2_SETTINGS_ENABLE_PUSH;
  iv[0].value = 0;
  iv[1].settings_id = NGHTTP2_SETTINGS_INITIAL_WINDOW_SIZE;
  iv[1].value = (1 << client_->worker->config->window_bits) - 1;

  rv = nghttp2_submit_settings(session_, NGHTTP2_FLAG_NONE, iv,
                               sizeof(iv) / sizeof(iv[0]));

  assert(rv == 0);

  auto extra_connection_window =
    (1 << client_->worker->config->connection_window_bits) - 1
    - NGHTTP2_INITIAL_CONNECTION_WINDOW_SIZE;
  if(extra_connection_window != 0) {
    nghttp2_submit_window_update(session_, NGHTTP2_FLAG_NONE, 0,
                                 extra_connection_window);
  }

  bufferevent_write(client_->bev, NGHTTP2_CLIENT_CONNECTION_PREFACE,
                    NGHTTP2_CLIENT_CONNECTION_PREFACE_LEN);
}

void Http2Session::submit_request()
{
  auto config = client_->worker->config;
  auto& nva = config->nva[client_->reqidx++];

  if(client_->reqidx == config->nva.size()) {
    client_->reqidx = 0;
  }

  nghttp2_submit_request(session_, nullptr, nva.data(), nva.size(),
                         nullptr, nullptr);
}

ssize_t Http2Session::on_read()
{
  int rv;
  auto input = bufferevent_get_input(client_->bev);
  auto inputlen = evbuffer_get_length(input);
  auto mem = evbuffer_pullup(input, -1);

  rv = nghttp2_session_mem_recv(session_, mem, inputlen);
  if(rv < 0) {
    return -1;
  }
  evbuffer_drain(input, rv);
  return rv;
}

int Http2Session::on_write()
{
  int rv;
  uint8_t buf[16384];
  auto output = bufferevent_get_output(client_->bev);
  util::EvbufferBuffer evbbuf(output, buf, sizeof(buf));
  for(;;) {
    const uint8_t *data;
    auto datalen = nghttp2_session_mem_send(session_, &data);

    if(datalen < 0) {
      return -1;
    }
    if(datalen == 0) {
      break;
    }
    rv = evbbuf.add(data, datalen);
    if(rv != 0) {
      return -1;
    }
  }
  rv = evbbuf.flush();
  if(rv != 0) {
    return -1;
  }
  if(nghttp2_session_want_read(session_) == 0 &&
     nghttp2_session_want_write(session_) == 0 &&
     evbuffer_get_length(output) == 0) {
    return -1;
  }
  return 0;
}

void Http2Session::terminate()
{
  nghttp2_session_terminate_session(session_, NGHTTP2_NO_ERROR);
}

} // namespace h2load
<commit_msg>h2load: Check return of nghttp2_submit_request<commit_after>/*
 * nghttp2 - HTTP/2 C Library
 *
 * Copyright (c) 2014 Tatsuhiro Tsujikawa
 *
 * 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.
 */
#include "h2load_http2_session.h"

#include <cassert>

#include "h2load.h"
#include "util.h"

using namespace nghttp2;

namespace h2load {

Http2Session::Http2Session(Client *client)
  : client_(client),
    session_(nullptr)
{}

Http2Session::~Http2Session()
{
  nghttp2_session_del(session_);
}

namespace {
int before_frame_send_callback
(nghttp2_session *session, const nghttp2_frame *frame, void *user_data)
{
  auto client = static_cast<Client*>(user_data);
  if(frame->hd.type == NGHTTP2_HEADERS &&
     frame->headers.cat == NGHTTP2_HCAT_REQUEST) {
    client->on_request(frame->hd.stream_id);
  }
  return 0;
}
} // namespace

namespace {
int on_header_callback(nghttp2_session *session,
                       const nghttp2_frame *frame,
                       const uint8_t *name, size_t namelen,
                       const uint8_t *value, size_t valuelen,
                       uint8_t flags,
                       void *user_data)
{
  auto client = static_cast<Client*>(user_data);
  if(frame->hd.type != NGHTTP2_HEADERS ||
     frame->headers.cat != NGHTTP2_HCAT_RESPONSE) {
    return 0;
  }
  client->on_header(frame->hd.stream_id, name, namelen, value, valuelen);
  return 0;
}
} // namespace

namespace {
int on_frame_recv_callback(nghttp2_session *session,
                           const nghttp2_frame *frame,
                           void *user_data)
{
  auto client = static_cast<Client*>(user_data);
  if(frame->hd.type != NGHTTP2_HEADERS ||
     frame->headers.cat != NGHTTP2_HCAT_RESPONSE) {
    return 0;
  }
  client->worker->stats.bytes_head += frame->hd.length;
  return 0;
}
} // namespace

namespace {
int on_data_chunk_recv_callback
(nghttp2_session *session, uint8_t flags, int32_t stream_id,
 const uint8_t *data, size_t len, void *user_data)
{
  auto client = static_cast<Client*>(user_data);
  client->worker->stats.bytes_body += len;
  return 0;
}
} // namespace

namespace {
int on_stream_close_callback
(nghttp2_session *session, int32_t stream_id, nghttp2_error_code error_code,
 void *user_data)
{
  auto client = static_cast<Client*>(user_data);
  client->on_stream_close(stream_id, error_code == NGHTTP2_NO_ERROR);
  return 0;
}
} // namespace

void Http2Session::on_connect()
{
  int rv;

  nghttp2_session_callbacks callbacks = {0};
  callbacks.before_frame_send_callback = before_frame_send_callback;
  callbacks.on_frame_recv_callback = on_frame_recv_callback;
  callbacks.on_data_chunk_recv_callback = on_data_chunk_recv_callback;
  callbacks.on_stream_close_callback = on_stream_close_callback;
  callbacks.on_header_callback = on_header_callback;

  nghttp2_session_client_new(&session_, &callbacks, client_);

  nghttp2_settings_entry iv[2];
  iv[0].settings_id = NGHTTP2_SETTINGS_ENABLE_PUSH;
  iv[0].value = 0;
  iv[1].settings_id = NGHTTP2_SETTINGS_INITIAL_WINDOW_SIZE;
  iv[1].value = (1 << client_->worker->config->window_bits) - 1;

  rv = nghttp2_submit_settings(session_, NGHTTP2_FLAG_NONE, iv,
                               sizeof(iv) / sizeof(iv[0]));

  assert(rv == 0);

  auto extra_connection_window =
    (1 << client_->worker->config->connection_window_bits) - 1
    - NGHTTP2_INITIAL_CONNECTION_WINDOW_SIZE;
  if(extra_connection_window != 0) {
    nghttp2_submit_window_update(session_, NGHTTP2_FLAG_NONE, 0,
                                 extra_connection_window);
  }

  bufferevent_write(client_->bev, NGHTTP2_CLIENT_CONNECTION_PREFACE,
                    NGHTTP2_CLIENT_CONNECTION_PREFACE_LEN);
}

void Http2Session::submit_request()
{
  int rv;
  auto config = client_->worker->config;
  auto& nva = config->nva[client_->reqidx++];

  if(client_->reqidx == config->nva.size()) {
    client_->reqidx = 0;
  }

  rv = nghttp2_submit_request(session_, nullptr, nva.data(), nva.size(),
                              nullptr, nullptr);
  assert(rv == 0);
}

ssize_t Http2Session::on_read()
{
  int rv;
  auto input = bufferevent_get_input(client_->bev);
  auto inputlen = evbuffer_get_length(input);
  auto mem = evbuffer_pullup(input, -1);

  rv = nghttp2_session_mem_recv(session_, mem, inputlen);
  if(rv < 0) {
    return -1;
  }
  evbuffer_drain(input, rv);
  return rv;
}

int Http2Session::on_write()
{
  int rv;
  uint8_t buf[16384];
  auto output = bufferevent_get_output(client_->bev);
  util::EvbufferBuffer evbbuf(output, buf, sizeof(buf));
  for(;;) {
    const uint8_t *data;
    auto datalen = nghttp2_session_mem_send(session_, &data);

    if(datalen < 0) {
      return -1;
    }
    if(datalen == 0) {
      break;
    }
    rv = evbbuf.add(data, datalen);
    if(rv != 0) {
      return -1;
    }
  }
  rv = evbbuf.flush();
  if(rv != 0) {
    return -1;
  }
  if(nghttp2_session_want_read(session_) == 0 &&
     nghttp2_session_want_write(session_) == 0 &&
     evbuffer_get_length(output) == 0) {
    return -1;
  }
  return 0;
}

void Http2Session::terminate()
{
  nghttp2_session_terminate_session(session_, NGHTTP2_NO_ERROR);
}

} // namespace h2load
<|endoftext|>