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