// qhash.sip generated by MetaSIP on Sun Nov  9 16:48:00 2014
//
// This file is part of the QtCore Python extension module.
//
// Copyright (c) 2014 Riverbank Computing Limited <info@riverbankcomputing.com>
// 
// This file is part of PyQt.
// 
// This file may be used under the terms of the GNU General Public
// License versions 2.0 or 3.0 as published by the Free Software
// Foundation and appearing in the files LICENSE.GPL2 and LICENSE.GPL3
// included in the packaging of this file.  Alternatively you may (at
// your option) use any later version of the GNU General Public
// License if such license has been publicly approved by Riverbank
// Computing Limited (or its successors, if any) and the KDE Free Qt
// Foundation. In addition, as a special exception, Riverbank gives you
// certain additional rights. These rights are described in the Riverbank
// GPL Exception version 1.1, which can be found in the file
// GPL_EXCEPTION.txt in this package.
// 
// If you are unsure which license is appropriate for your use, please
// contact the sales department at sales@riverbankcomputing.com.
// 
// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.


// QHash<TYPE1, TYPE2> is implemented as a Python dictionary.
template<TYPE1, TYPE2>
%MappedType QHash<TYPE1, TYPE2> /DocType="dict-of-TYPE1-TYPE2"/
{
%TypeHeaderCode
#include <qhash.h>
%End

%ConvertFromTypeCode
    // Create the dictionary.
    PyObject *d = PyDict_New();

    if (!d)
        return NULL;

    // Set the dictionary elements.
    QHash<TYPE1, TYPE2>::const_iterator i = sipCpp->constBegin();

    while (i != sipCpp->constEnd())
    {
        TYPE1 *t1 = new TYPE1(i.key());
        TYPE2 *t2 = new TYPE2(i.value());

        PyObject *t1obj = sipConvertFromNewType(t1, sipType_TYPE1, sipTransferObj);
        PyObject *t2obj = sipConvertFromNewType(t2, sipType_TYPE2, sipTransferObj);

        if (t1obj == NULL || t2obj == NULL || PyDict_SetItem(d, t1obj, t2obj) < 0)
        {
            Py_DECREF(d);

            if (t1obj)
            {
                Py_DECREF(t1obj);
            }
            else
            {
                delete t1;
            }

            if (t2obj)
            {
                Py_DECREF(t2obj);
            }
            else
            {
                delete t2;
            }

            return NULL;
        }

        Py_DECREF(t1obj);
        Py_DECREF(t2obj);

        ++i;
    }

    return d;
%End

%ConvertToTypeCode
    PyObject *t1obj, *t2obj;
    SIP_SSIZE_T i = 0;

    // Check the type if that is all that is required.
    if (sipIsErr == NULL)
    {
        if (!PyDict_Check(sipPy))
            return 0;

        while (PyDict_Next(sipPy, &i, &t1obj, &t2obj))
        {
            if (!sipCanConvertToType(t1obj, sipType_TYPE1, SIP_NOT_NONE))
                return 0;

            if (!sipCanConvertToType(t2obj, sipType_TYPE2, SIP_NOT_NONE))
                return 0;
        } 

        return 1;
    }

    QHash<TYPE1, TYPE2> *qm = new QHash<TYPE1, TYPE2>;
 
    while (PyDict_Next(sipPy, &i, &t1obj, &t2obj))
    {
        int state1, state2;

        TYPE1 *t1 = reinterpret_cast<TYPE1 *>(sipConvertToType(t1obj, sipType_TYPE1, sipTransferObj, SIP_NOT_NONE, &state1, sipIsErr));
        TYPE2 *t2 = reinterpret_cast<TYPE2 *>(sipConvertToType(t2obj, sipType_TYPE2, sipTransferObj, SIP_NOT_NONE, &state2, sipIsErr));
 
        if (*sipIsErr)
        {
            sipReleaseType(t1, sipType_TYPE1, state1);
            sipReleaseType(t2, sipType_TYPE2, state2);

            delete qm;
            return 0;
        }

        qm->insert(*t1, *t2);

        sipReleaseType(t1, sipType_TYPE1, state1);
        sipReleaseType(t2, sipType_TYPE2, state2);
    }
 
    *sipCppPtr = qm;
 
    return sipGetState(sipTransferObj);
%End
};
// QHash<int, TYPE> is implemented as a Python dictionary.
template<TYPE>
%MappedType QHash<int, TYPE> /DocType="dict-of-int-TYPE"/
{
%TypeHeaderCode
#include <qhash.h>
%End

%ConvertFromTypeCode
    // Create the dictionary.
    PyObject *d = PyDict_New();

    if (!d)
        return NULL;

    // Set the dictionary elements.
    QHash<int, TYPE>::const_iterator i = sipCpp->constBegin();

    while (i != sipCpp->constEnd())
    {
        TYPE *t = new TYPE(i.value());

        PyObject *kobj = SIPLong_FromLong(i.key());
        PyObject *tobj = sipConvertFromNewType(t, sipType_TYPE, sipTransferObj);

        if (kobj == NULL || tobj == NULL || PyDict_SetItem(d, kobj, tobj) < 0)
        {
            Py_DECREF(d);

            if (kobj)
            {
                Py_DECREF(kobj);
            }

            if (tobj)
            {
                Py_DECREF(tobj);
            }
            else
            {
                delete t;
            }

            return NULL;
        }

        Py_DECREF(kobj);
        Py_DECREF(tobj);

        ++i;
    }

    return d;
%End

%ConvertToTypeCode
    PyObject *kobj, *tobj;
    SIP_SSIZE_T i = 0;

    // Check the type if that is all that is required.
    if (sipIsErr == NULL)
    {
        if (!PyDict_Check(sipPy))
            return 0;

        while (PyDict_Next(sipPy, &i, &kobj, &tobj))
            if (!sipCanConvertToType(tobj, sipType_TYPE, SIP_NOT_NONE))
                return 0;

        return 1;
    }

    QHash<int, TYPE> *qm = new QHash<int, TYPE>;
 
    while (PyDict_Next(sipPy, &i, &kobj, &tobj))
    {
        int state, k = SIPLong_AsLong(kobj);
        TYPE *t = reinterpret_cast<TYPE *>(sipConvertToType(tobj, sipType_TYPE, sipTransferObj, SIP_NOT_NONE, &state, sipIsErr));
 
        if (*sipIsErr)
        {
            sipReleaseType(t, sipType_TYPE, state);

            delete qm;
            return 0;
        }

        qm->insert(k, *t);

        sipReleaseType(t, sipType_TYPE, state);
    }
 
    *sipCppPtr = qm;
 
    return sipGetState(sipTransferObj);
%End
};
// QMultiHash<TYPE1, TYPE2> is implemented as a Python dictionary.
template<TYPE1, TYPE2>
%MappedType QMultiHash<TYPE1, TYPE2> /DocType="dict-of-TYPE1-list-of-TYPE2"/
{
%TypeHeaderCode
#include <qhash.h>
%End

%ConvertFromTypeCode
    // Create the dictionary.
    PyObject *d = PyDict_New();

    if (!d)
        return NULL;

    // Set the dictionary elements.
    QMultiHash<TYPE1, TYPE2>::const_iterator i = sipCpp->constBegin();

    while (i != sipCpp->constEnd())
    {
        TYPE1 *t1 = new TYPE1(i.key());
        TYPE2 *t2 = new TYPE2(i.value());

        PyObject *t1obj = sipConvertFromNewType(t1, sipType_TYPE1, sipTransferObj);
        PyObject *t2obj = sipConvertFromNewType(t2, sipType_TYPE2, sipTransferObj);

        if (t1obj == NULL || t2obj == NULL)
        {
            Py_DECREF(d);

            if (t1obj)
            {
                Py_DECREF(t1obj);
            }
            else
            {
                delete t1;
            }

            if (t2obj)
            {
                Py_DECREF(t2obj);
            }
            else
            {
                delete t2;
            }

            return NULL;
        }

        PyObject *vobj = PyDict_GetItem(d, t1obj);

        if (vobj != NULL)
        {
            // Newer items are inserted (rather than appended) to mimic the
            // behaviour of QMultiHash::find() that returns an iterator that
            // initially references the most recently inserted item.
            if (PyList_Insert(vobj, 0, t2obj) < 0)
                vobj = NULL;
        }
        else
        {
            if ((vobj = PyList_New(1)) != NULL)
            {
                PyList_SET_ITEM(vobj, 0, t2obj);
                Py_INCREF(t2obj);

                if (PyDict_SetItem(d, t1obj, vobj) < 0)
                {
                    Py_DECREF(vobj);
                    vobj = NULL;
                }
            }
        }

        Py_DECREF(t1obj);
        Py_DECREF(t2obj);

        if (vobj == NULL)
        {
            Py_DECREF(d);

            return NULL;
        }

        ++i;
    }

    return d;
%End

%ConvertToTypeCode
    PyObject *t1obj, *t2obj, *vobj;
    SIP_SSIZE_T i = 0, vi, len;

    // Check the type if that is all that is required.
    if (sipIsErr == NULL)
    {
        if (!PyDict_Check(sipPy))
            return 0;

        while (PyDict_Next(sipPy, &i, &t1obj, &vobj))
        {
            if (!sipCanConvertToType(t1obj, sipType_TYPE1, SIP_NOT_NONE))
                return 0;

            if (!PySequence_Check(vobj))
                return 0;

            len = PySequence_Size(vobj);

            // The sequence cannot be empty.
            if (len <= 0)
                return 0;

            for (vi = 0; vi < len; ++vi)
            {
               if ((t2obj = PySequence_ITEM(vobj, vi)) == NULL)
                    return 0;

                if (!sipCanConvertToType(t2obj, sipType_TYPE2, SIP_NOT_NONE))
                {
                    Py_DECREF(t2obj);
                    return 0;
                }

                Py_DECREF(t2obj);
            }
        } 

        return 1;
    }

    QMultiHash<TYPE1, TYPE2> *qm = new QMultiHash<TYPE1, TYPE2>;
 
    while (PyDict_Next(sipPy, &i, &t1obj, &vobj))
    {
        int state1;

        TYPE1 *t1 = reinterpret_cast<TYPE1 *>(sipConvertToType(t1obj, sipType_TYPE1, sipTransferObj, SIP_NOT_NONE, &state1, sipIsErr));

        // Insert from the end of the sequence (see the above comment about
        // QMultiHash::find().
        for (vi = PySequence_Size(vobj) - 1; vi >= 0; --vi)
        {
            if ((t2obj = PySequence_ITEM(vobj, vi)) == NULL)
                *sipIsErr = 1;

            int state2;

            TYPE2 *t2 = reinterpret_cast<TYPE2 *>(sipConvertToType(t2obj, sipType_TYPE2, sipTransferObj, SIP_NOT_NONE, &state2, sipIsErr));
 
            if (*sipIsErr)
            {
                Py_XDECREF(t2obj);

                sipReleaseType(t1, sipType_TYPE1, state1);
                sipReleaseType(t2, sipType_TYPE2, state2);

                delete qm;
                return 0;
            }

            qm->insert(*t1, *t2);

            sipReleaseType(t2, sipType_TYPE2, state2);
            Py_DECREF(t2obj);
        }

        sipReleaseType(t1, sipType_TYPE1, state1);
    }
 
    *sipCppPtr = qm;
 
    return sipGetState(sipTransferObj);
%End
};
