graphicsdeviceinterface/gdi/sgdi/hextree.cpp
author hgs
Tue, 22 Jun 2010 15:21:29 +0300
changeset 103 2717213c588a
permissions -rw-r--r--
201024
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
103
hgs
parents:
diff changeset
     1
// Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
hgs
parents:
diff changeset
     2
// All rights reserved.
hgs
parents:
diff changeset
     3
// This component and the accompanying materials are made available
hgs
parents:
diff changeset
     4
// under the terms of "Eclipse Public License v1.0"
hgs
parents:
diff changeset
     5
// which accompanies this distribution, and is available
hgs
parents:
diff changeset
     6
// at the URL "http://www.eclipse.org/legal/epl-v10.html".
hgs
parents:
diff changeset
     7
//
hgs
parents:
diff changeset
     8
// Initial Contributors:
hgs
parents:
diff changeset
     9
// Nokia Corporation - initial contribution.
hgs
parents:
diff changeset
    10
//
hgs
parents:
diff changeset
    11
// Contributors:
hgs
parents:
diff changeset
    12
//
hgs
parents:
diff changeset
    13
// Description:
hgs
parents:
diff changeset
    14
// Hexadecimal trees - implementation
hgs
parents:
diff changeset
    15
//
hgs
parents:
diff changeset
    16
hgs
parents:
diff changeset
    17
#include <hextree.h>
hgs
parents:
diff changeset
    18
#include <e32atomics.h>
hgs
parents:
diff changeset
    19
hgs
parents:
diff changeset
    20
EXPORT_C RHexTreeBase::RHexTreeBase(RHeap* aHeap)
hgs
parents:
diff changeset
    21
    : iHeap(aHeap)
hgs
parents:
diff changeset
    22
    {
hgs
parents:
diff changeset
    23
    Mem::FillZ(iRootOffsets, sizeof(iRootOffsets));
hgs
parents:
diff changeset
    24
    }
hgs
parents:
diff changeset
    25
hgs
parents:
diff changeset
    26
EXPORT_C TInt RHexTreeBase::SetAt(TUint aKey, TAny* aValue)
hgs
parents:
diff changeset
    27
    {
hgs
parents:
diff changeset
    28
    TUint mask = 0xF0000000;
hgs
parents:
diff changeset
    29
    for (TInt height = EMaxNumHexDigits; height > 1; --height)
hgs
parents:
diff changeset
    30
        {
hgs
parents:
diff changeset
    31
        if ((aKey & mask) != 0)
hgs
parents:
diff changeset
    32
            {
hgs
parents:
diff changeset
    33
            return SetAt(aKey, aValue, height);
hgs
parents:
diff changeset
    34
            }
hgs
parents:
diff changeset
    35
        mask >>= 4;
hgs
parents:
diff changeset
    36
        }
hgs
parents:
diff changeset
    37
    return SetAt(aKey, aValue, 1);
hgs
parents:
diff changeset
    38
    }
hgs
parents:
diff changeset
    39
hgs
parents:
diff changeset
    40
EXPORT_C TAny* RHexTreeBase::At(TUint aKey) const
hgs
parents:
diff changeset
    41
    {
hgs
parents:
diff changeset
    42
    TUint mask = 0xF0000000;
hgs
parents:
diff changeset
    43
    for (TInt height = EMaxNumHexDigits; height > 1; --height)
hgs
parents:
diff changeset
    44
        {
hgs
parents:
diff changeset
    45
        if ((aKey & mask) != 0)
hgs
parents:
diff changeset
    46
            {
hgs
parents:
diff changeset
    47
            return At(aKey, height);
hgs
parents:
diff changeset
    48
            }
hgs
parents:
diff changeset
    49
        mask >>= 4;
hgs
parents:
diff changeset
    50
        }
hgs
parents:
diff changeset
    51
    return At(aKey, 1);
hgs
parents:
diff changeset
    52
    }
hgs
parents:
diff changeset
    53
hgs
parents:
diff changeset
    54
/**
hgs
parents:
diff changeset
    55
Empties this associative array and frees all memory allocated both for the
hgs
parents:
diff changeset
    56
associative array implementation and for the values that have been added to
hgs
parents:
diff changeset
    57
this associative array.
hgs
parents:
diff changeset
    58
hgs
parents:
diff changeset
    59
The internal state of this associative array is reset so that it can be reused
hgs
parents:
diff changeset
    60
or allowed to go out of scope after a call to this function.
hgs
parents:
diff changeset
    61
*/
hgs
parents:
diff changeset
    62
EXPORT_C void RHexTreeBase::ResetAndDestroy()
hgs
parents:
diff changeset
    63
    {
hgs
parents:
diff changeset
    64
    for (TInt height = 1; height <= EMaxNumHexDigits; ++height)
hgs
parents:
diff changeset
    65
        {
hgs
parents:
diff changeset
    66
        TInt offset = iRootOffsets[height - 1];
hgs
parents:
diff changeset
    67
        if (offset != 0)
hgs
parents:
diff changeset
    68
            {
hgs
parents:
diff changeset
    69
            TAny* root = PtrAdd(this, offset);
hgs
parents:
diff changeset
    70
            ResetAndDestroy(height, root, 1);
hgs
parents:
diff changeset
    71
            iRootOffsets[height - 1] = 0;
hgs
parents:
diff changeset
    72
            }
hgs
parents:
diff changeset
    73
        }
hgs
parents:
diff changeset
    74
    }
hgs
parents:
diff changeset
    75
hgs
parents:
diff changeset
    76
TInt RHexTreeBase::SetAt(TUint aKey, TAny* aLeaf, TInt aHeight)
hgs
parents:
diff changeset
    77
    {
hgs
parents:
diff changeset
    78
    TInt err;
hgs
parents:
diff changeset
    79
    TInt offset = iRootOffsets[aHeight - 1];
hgs
parents:
diff changeset
    80
    if (offset == 0)
hgs
parents:
diff changeset
    81
        {
hgs
parents:
diff changeset
    82
        TAny* root = iHeap->AllocZ(aHeight > 1 ? sizeof(TInt) * 15 : sizeof(TInt) * 16);
hgs
parents:
diff changeset
    83
        if (!root)
hgs
parents:
diff changeset
    84
            {
hgs
parents:
diff changeset
    85
            return KErrNoMemory;
hgs
parents:
diff changeset
    86
            }
hgs
parents:
diff changeset
    87
        err = SetAt(aKey, aLeaf, aHeight, root, 1);
hgs
parents:
diff changeset
    88
        if (err == KErrNone)
hgs
parents:
diff changeset
    89
            {
hgs
parents:
diff changeset
    90
            __e32_atomic_store_rel32(&iRootOffsets[aHeight - 1], reinterpret_cast<TInt>(root) - reinterpret_cast<TInt>(this));
hgs
parents:
diff changeset
    91
            }
hgs
parents:
diff changeset
    92
        else
hgs
parents:
diff changeset
    93
            {
hgs
parents:
diff changeset
    94
            iHeap->Free(root);
hgs
parents:
diff changeset
    95
            }
hgs
parents:
diff changeset
    96
        }
hgs
parents:
diff changeset
    97
    else
hgs
parents:
diff changeset
    98
        {
hgs
parents:
diff changeset
    99
        TAny* root = PtrAdd(this, offset);
hgs
parents:
diff changeset
   100
        err = SetAt(aKey, aLeaf, aHeight, root, 1);
hgs
parents:
diff changeset
   101
        }
hgs
parents:
diff changeset
   102
    return err;
hgs
parents:
diff changeset
   103
    }
hgs
parents:
diff changeset
   104
hgs
parents:
diff changeset
   105
TInt RHexTreeBase::SetAt(TUint aKey, TAny* aLeaf, TInt aHeight, TAny* aNode, TInt aLevel)
hgs
parents:
diff changeset
   106
    {
hgs
parents:
diff changeset
   107
    TInt err = KErrNone;
hgs
parents:
diff changeset
   108
    TInt branch = (aKey >> ((aHeight - aLevel) << 2)) & 0xF;
hgs
parents:
diff changeset
   109
    if (aLevel == 1 && aHeight > 1)
hgs
parents:
diff changeset
   110
        {
hgs
parents:
diff changeset
   111
        --branch;
hgs
parents:
diff changeset
   112
        }
hgs
parents:
diff changeset
   113
    TInt offset = static_cast<TInt*>(aNode)[branch];
hgs
parents:
diff changeset
   114
    if (aLevel == aHeight)
hgs
parents:
diff changeset
   115
        {
hgs
parents:
diff changeset
   116
        if (offset == 0)
hgs
parents:
diff changeset
   117
            {
hgs
parents:
diff changeset
   118
            __e32_atomic_store_rel32(&static_cast<TInt*>(aNode)[branch], reinterpret_cast<TInt>(aLeaf) - reinterpret_cast<TInt>(aNode));
hgs
parents:
diff changeset
   119
            }
hgs
parents:
diff changeset
   120
        else
hgs
parents:
diff changeset
   121
            {
hgs
parents:
diff changeset
   122
            err = KErrAlreadyExists;
hgs
parents:
diff changeset
   123
            }
hgs
parents:
diff changeset
   124
        }
hgs
parents:
diff changeset
   125
    else if (offset == 0)
hgs
parents:
diff changeset
   126
        {
hgs
parents:
diff changeset
   127
        TAny* newNode = iHeap->AllocZ(sizeof(TInt) * 16);
hgs
parents:
diff changeset
   128
        if (!newNode)
hgs
parents:
diff changeset
   129
            {
hgs
parents:
diff changeset
   130
            return KErrNoMemory;
hgs
parents:
diff changeset
   131
            }
hgs
parents:
diff changeset
   132
        err = SetAt(aKey, aLeaf, aHeight, newNode, aLevel + 1);
hgs
parents:
diff changeset
   133
        if (err == KErrNone)
hgs
parents:
diff changeset
   134
            {
hgs
parents:
diff changeset
   135
            __e32_atomic_store_rel32(&static_cast<TInt*>(aNode)[branch], reinterpret_cast<TInt>(newNode) - reinterpret_cast<TInt>(aNode));
hgs
parents:
diff changeset
   136
            }
hgs
parents:
diff changeset
   137
        else
hgs
parents:
diff changeset
   138
            {
hgs
parents:
diff changeset
   139
            iHeap->Free(newNode);
hgs
parents:
diff changeset
   140
            }
hgs
parents:
diff changeset
   141
        }
hgs
parents:
diff changeset
   142
    else
hgs
parents:
diff changeset
   143
        {
hgs
parents:
diff changeset
   144
        TAny* nextNode = PtrAdd(aNode, offset);
hgs
parents:
diff changeset
   145
        err = SetAt(aKey, aLeaf, aHeight, nextNode, aLevel + 1);
hgs
parents:
diff changeset
   146
        }
hgs
parents:
diff changeset
   147
    return err;
hgs
parents:
diff changeset
   148
    }
hgs
parents:
diff changeset
   149
hgs
parents:
diff changeset
   150
TAny* RHexTreeBase::At(TUint aKey, TInt aHeight) const
hgs
parents:
diff changeset
   151
    {
hgs
parents:
diff changeset
   152
    TInt offset = __e32_atomic_load_acq32(&iRootOffsets[aHeight - 1]);
hgs
parents:
diff changeset
   153
    if (offset == 0)
hgs
parents:
diff changeset
   154
        {
hgs
parents:
diff changeset
   155
        return NULL;
hgs
parents:
diff changeset
   156
        }
hgs
parents:
diff changeset
   157
    const TAny* node = PtrAdd(this, offset);
hgs
parents:
diff changeset
   158
    for (TInt level = 1; level <= aHeight; ++level)
hgs
parents:
diff changeset
   159
        {
hgs
parents:
diff changeset
   160
        TInt branch = (aKey >> ((aHeight - level) << 2)) & 0xF;
hgs
parents:
diff changeset
   161
        if (level == 1 && aHeight > 1)
hgs
parents:
diff changeset
   162
            {
hgs
parents:
diff changeset
   163
            --branch;
hgs
parents:
diff changeset
   164
            }
hgs
parents:
diff changeset
   165
        offset = __e32_atomic_load_acq32(&static_cast<const TInt*>(node)[branch]);
hgs
parents:
diff changeset
   166
        if (offset == 0)
hgs
parents:
diff changeset
   167
            {
hgs
parents:
diff changeset
   168
            return NULL;
hgs
parents:
diff changeset
   169
            }
hgs
parents:
diff changeset
   170
        node = PtrAdd(node, offset);
hgs
parents:
diff changeset
   171
        }
hgs
parents:
diff changeset
   172
    return const_cast<TAny*>(node);
hgs
parents:
diff changeset
   173
    }
hgs
parents:
diff changeset
   174
hgs
parents:
diff changeset
   175
void RHexTreeBase::ResetAndDestroy(TInt aHeight, TAny* aNode, TInt aLevel)
hgs
parents:
diff changeset
   176
    {
hgs
parents:
diff changeset
   177
    TInt maxNumBranches = (aLevel == 1 && aHeight > 1 ? 15 : 16);
hgs
parents:
diff changeset
   178
    for (TInt branch = 0; branch < maxNumBranches; ++branch)
hgs
parents:
diff changeset
   179
        {
hgs
parents:
diff changeset
   180
        TInt offset = static_cast<TInt*>(aNode)[branch];
hgs
parents:
diff changeset
   181
        if (offset != 0)
hgs
parents:
diff changeset
   182
            {
hgs
parents:
diff changeset
   183
            TAny* nextNode = PtrAdd(aNode, offset);
hgs
parents:
diff changeset
   184
            if (aLevel == aHeight)
hgs
parents:
diff changeset
   185
                {
hgs
parents:
diff changeset
   186
                iHeap->Free(nextNode);
hgs
parents:
diff changeset
   187
                }
hgs
parents:
diff changeset
   188
            else
hgs
parents:
diff changeset
   189
                {
hgs
parents:
diff changeset
   190
                ResetAndDestroy(aHeight, nextNode, aLevel + 1);
hgs
parents:
diff changeset
   191
                }
hgs
parents:
diff changeset
   192
            }
hgs
parents:
diff changeset
   193
        }
hgs
parents:
diff changeset
   194
    iHeap->Free(aNode);
hgs
parents:
diff changeset
   195
    }