/****************************************************************************
Desc:	Reinsert all entries given a new root block.
		Caller will release 'this'.  Used ONLY for building the first
		ROOT and two leaves of the tree.
****************************************************************************/
RCODE F_BtreeLeaf::split(
    F_BtreeRoot *	pNewRoot)		// New Non-leaf root
{
    RCODE				rc = NE_FLM_OK;
    FLMBYTE *		pucEntry;
    FLMUINT			uiPos;
    FLMUINT			uiEntryCount = entryCount();
    FLMUINT			uiMid = (uiEntryCount + 1) >> 1;

    if (RC_BAD( rc = pNewRoot->setupTree( ENTRY_POS(uiMid),
                                          ACCESS_BTREE_LEAF, NULL, NULL)))
    {
        goto Exit;
    }

    for (uiPos = 0; uiPos < uiEntryCount; uiPos++)
    {
        pucEntry = ENTRY_POS( uiPos);
        if ((rc = pNewRoot->search( pucEntry)) != NE_FLM_NOT_FOUND)
        {
            rc = RC_SET_AND_ASSERT( NE_FLM_FAILURE);
            goto Exit;
        }

        if (RC_BAD( rc = pNewRoot->insert( pucEntry)))
        {
            goto Exit;
        }
    }

Exit:

    return( rc);
}
Пример #2
0
std::vector<TargetValue> ResultSet::getRowAtNoTranslations(const size_t logical_index) const {
  if (logical_index >= entryCount()) {
    return {};
  }
  const auto entry_idx = permutation_.empty() ? logical_index : permutation_[logical_index];
  return getRowAt(entry_idx, false, false, false);
}
/****************************************************************************
Desc:	Return the next entry in the result set.  If the result set
		is not positioned then the first entry will be returned.
****************************************************************************/
RCODE F_BtreeBlk::getNext(
    void *		pvEntryBuffer)
{
    RCODE			rc = NE_FLM_OK;
    FLMUINT		uiPos = m_uiPosition;

    // Position to the next/first entry.

    if (uiPos == DYNSSET_POSITION_NOT_SET)
    {
        uiPos = 0;
    }
    else
    {
        if (++uiPos > entryCount())
        {
            rc = RC_SET( NE_FLM_EOF_HIT);
            goto Exit;
        }
    }
    f_memcpy( pvEntryBuffer, ENTRY_POS(uiPos), m_uiEntrySize);
    m_uiPosition = uiPos;

Exit:

    return( rc);
}
Пример #4
0
std::vector<TargetValue> ResultSet::getNextRowImpl(const bool translate_strings, const bool decimal_to_double) const {
  auto entry_buff_idx = advanceCursorToNextEntry();
  if (keep_first_ && fetched_so_far_ >= drop_first_ + keep_first_) {
    return {};
  }

  if (crt_row_buff_idx_ >= entryCount()) {
    CHECK_EQ(entryCount(), crt_row_buff_idx_);
    return {};
  }
  auto row = getRowAt(entry_buff_idx, translate_strings, decimal_to_double, false);
  CHECK(!row.empty());
  ++crt_row_buff_idx_;
  ++fetched_so_far_;

  return row;
}
Пример #5
0
bool ResultSet::isRowAtEmpty(const size_t logical_index) const {
  if (logical_index >= entryCount()) {
    return true;
  }
  const auto entry_idx = permutation_.empty() ? logical_index : permutation_[logical_index];
  const auto storage_lookup_result = findStorage(entry_idx);
  const auto storage = storage_lookup_result.storage_ptr;
  const auto local_entry_idx = storage_lookup_result.fixedup_entry_idx;
  return storage->isEmptyEntry(local_entry_idx);
}
/****************************************************************************
Desc:	Insert the entry into the buffer.
****************************************************************************/
RCODE F_BtreeBlk::insertEntry(
    void *		pvEntry,
    FLMUINT		uiChildAddr)
{
    RCODE			rc = NE_FLM_OK;
    FLMBYTE *	pucCurEntry;
    FLMUINT		uiShiftBytes;		// Always shift down

    if( entryCount() >= m_uiNumSlots)
    {
        rc = RC_SET( NE_FLM_FAILURE);
        goto Exit;
    }
    flmAssert( m_uiPosition != DYNSSET_POSITION_NOT_SET);
    pucCurEntry = ENTRY_POS( m_uiPosition);
    if ((uiShiftBytes = (entryCount() - m_uiPosition) *
                        (m_uiEntrySize + m_uiEntryOvhd)) != 0)
    {

        // Big hairy assert.  Finds coding bugs and corruptions.

        flmAssert( m_uiPosition * (m_uiEntrySize + m_uiEntryOvhd) +
                   uiShiftBytes < DYNSSET_BLOCK_SIZE - sizeof( FixedBlkHdr));

        f_memmove( pucCurEntry + m_uiEntrySize + m_uiEntryOvhd,
                   pucCurEntry, uiShiftBytes);
    }
    f_memcpy( pucCurEntry, pvEntry, m_uiEntrySize);
    if( m_uiEntryOvhd)
    {
        UD2FBA( (FLMUINT32)uiChildAddr, &pucCurEntry[m_uiEntrySize]);
    }
    entryCount( entryCount() + 1);
    m_uiPosition++;
    m_bDirty = TRUE;

Exit:

    return( rc);
}
Пример #7
0
// Not all entries in the buffer represent a valid row. Advance the internal cursor
// used for the getNextRow method to the next row which is valid.
size_t ResultSet::advanceCursorToNextEntry() const {
  while (crt_row_buff_idx_ < entryCount()) {
    const auto entry_idx = permutation_.empty() ? crt_row_buff_idx_ : permutation_[crt_row_buff_idx_];
    const auto storage_lookup_result = findStorage(entry_idx);
    const auto storage = storage_lookup_result.storage_ptr;
    const auto fixedup_entry_idx = storage_lookup_result.fixedup_entry_idx;
    if (!storage->isEmptyEntry(fixedup_entry_idx)) {
      break;
    }
    ++crt_row_buff_idx_;
  }
  if (permutation_.empty()) {
    return crt_row_buff_idx_;
  }
  CHECK_LE(crt_row_buff_idx_, permutation_.size());
  return crt_row_buff_idx_ == permutation_.size() ? crt_row_buff_idx_ : permutation_[crt_row_buff_idx_];
}
/****************************************************************************
Desc:	Setup the block as a new block
****************************************************************************/
void F_BtreeBlk::reset(
    eDynRSetBlkTypes	eBlkType)
{
    m_eBlkType = eBlkType;

    if (eBlkType == ACCESS_BTREE_ROOT || eBlkType == ACCESS_BTREE_NON_LEAF)
    {
        m_uiEntryOvhd = 4;
    }
    else
    {
        m_uiEntryOvhd = 0;
    }
    m_uiNumSlots = (DYNSSET_BLOCK_SIZE - sizeof( FixedBlkHdr)) /
                   ( m_uiEntrySize + m_uiEntryOvhd);
    entryCount( 0);
    m_uiPosition = DYNSSET_POSITION_NOT_SET;
    m_bDirty = FALSE;
}
/****************************************************************************
Desc:	Return the last entry in the result set.
****************************************************************************/
RCODE F_BtreeBlk::getLast(
    void *		pvEntryBuffer)
{
    RCODE			rc = NE_FLM_OK;
    FLMUINT		uiPos = entryCount();

    // Position to the next/first entry.

    if (uiPos == 0)
    {
        rc = RC_SET( NE_FLM_EOF_HIT);
        goto Exit;
    }

    uiPos--;
    f_memcpy( pvEntryBuffer, ENTRY_POS(uiPos), m_uiEntrySize);
    m_uiPosition = uiPos;

Exit:

    return( rc);
}
Пример #10
0
/****************************************************************************
Desc:	Split the root block and make two new non-leaf blocks.
		The secret here is that the root block never moves (cheers!).
		This takes a little longer but is worth the work because the
		root block never goes out to disk and is not in the cache.
****************************************************************************/
RCODE F_BtreeRoot::split(
    void *			pvCurEntry,
    FLMUINT			uiCurChildAddr)
{
    RCODE				rc = NE_FLM_OK;
    FLMBYTE *		pucEntry;
    FLMBYTE *		pucChildAddr;
    F_BtreeBlk *		pLeftBlk;
    F_BtreeBlk *		pRightBlk;
    F_BtreeBlk *		pBlk;
    FLMUINT			uiChildAddr;
    FLMUINT			uiPos;
    FLMUINT			uiEntryCount = entryCount();
    FLMUINT			uiMid = (uiEntryCount + 1) >> 1;

    if (RC_BAD( rc = setupTree( NULL, ACCESS_BTREE_NON_LEAF,
                                &pLeftBlk, &pRightBlk)))
    {
        goto Exit;
    }

    // Call search entry once just to setup for insert.

    (void) pLeftBlk->searchEntry( ENTRY_POS( 0));

    // Take the entries from the root block and move into leafs.

    for (uiPos = 0; uiPos <= uiMid; uiPos++)
    {
        pucEntry = ENTRY_POS( uiPos);
        pucChildAddr = pucEntry + m_uiEntrySize;
        uiChildAddr = (FLMUINT)FB2UD(pucChildAddr);

        if (RC_BAD( rc = pLeftBlk->insertEntry( pucEntry, uiChildAddr)))
        {
            goto Exit;
        }
    }

    // Call search entry once just to setup for insert.

    (void) pRightBlk->searchEntry( ENTRY_POS( 0));

    for (uiPos = uiMid + 1; uiPos < uiEntryCount; uiPos++)
    {
        pucEntry = ENTRY_POS( uiPos);
        pucChildAddr = pucEntry + m_uiEntrySize;
        uiChildAddr = (FLMUINT)FB2UD(pucChildAddr);

        if ((rc = pRightBlk->searchEntry( pucEntry )) != NE_FLM_NOT_FOUND)
        {
            rc = RC_SET_AND_ASSERT( NE_FLM_FAILURE);
            goto Exit;
        }

        if (RC_BAD( rc = pRightBlk->insertEntry( pucEntry, uiChildAddr)))
        {
            goto Exit;
        }
    }

    // Reset the root block and insert new midpoint.

    entryCount( 0);
    lemBlk( pRightBlk->blkAddr());	// Duplicated just in case.
    pucEntry = ENTRY_POS( uiMid);

    if ((rc = searchEntry( pucEntry )) != NE_FLM_NOT_FOUND)
    {
        rc = RC_SET_AND_ASSERT( NE_FLM_FAILURE);
        goto Exit;
    }

    if (RC_BAD( rc = insertEntry( pucEntry, pLeftBlk->blkAddr() )))
    {
        goto Exit;
    }

    // Insert the current entry (parameters) into the left or right blk.
    // This could be done a number of different ways.
    (void) searchEntry( pvCurEntry, &uiChildAddr);
    if (RC_BAD( rc = readBlk( uiChildAddr, ACCESS_BTREE_NON_LEAF, &pBlk)))
    {
        goto Exit;
    }
    (void) pBlk->searchEntry( pvCurEntry);
    if (RC_BAD( rc = pBlk->insertEntry( pvCurEntry, uiCurChildAddr)))
    {
        goto Exit;
    }

Exit:

    return( rc);
}
Пример #11
0
/****************************************************************************
Desc:	Move first half of entries into new block.  Reset previous block
		to point to new block.  Add new last entry in new block to parent.
		Fixup prev/next linkages.
****************************************************************************/
RCODE F_BtreeBlk::split(
    F_BtreeRoot *	pRoot,
    FLMBYTE *		pucCurEntry,		// (in) Contains entry to insert
    FLMUINT			uiCurBlkAddr,		// (in) Blk addr if non-leaf
    FLMBYTE *		pucParentEntry,	// (out) Entry to insert into parent.
    FLMUINT *		puiNewBlkAddr)		// (out) New blk addr to insert into parent.
{
    RCODE				rc = NE_FLM_OK;
    F_BtreeBlk *		pPrevBlk;
    F_BtreeBlk *		pNewBlk = NULL;
    FLMBYTE *		pucEntry = NULL;
    FLMBYTE *		pucMidEntry;
    FLMBYTE *		pucChildAddr;
    FLMUINT			uiChildAddr;
    FLMUINT			uiPrevBlkAddr;
    FLMUINT			uiMid;
    FLMUINT			uiPos;
    FLMUINT			uiMoveBytes;
    FLMBOOL			bInserted = FALSE;

    // Allocate a new block for the split.

    if (RC_BAD( rc = pRoot->newBlk( &pNewBlk, blkType() )))
    {
        goto Exit;
    }
    pNewBlk->AddRef();				// Pin the block - may get flushed out.


    // the last half into the new block, but that would force the parent
    // entry to be changed.  This may take a little longer, but it is much
    // more easier to code.

    // Call search entry once just to setup for insert.

    (void) pNewBlk->searchEntry( ENTRY_POS( 0));

    // get the count and move more then half into the new block.

    uiMid = (entryCount() + 5) >> 1;
    uiChildAddr = FBTREE_END;

    for (uiPos = 0; uiPos < uiMid; uiPos++)
    {
        pucEntry = ENTRY_POS( uiPos);
        if (blkType() != ACCESS_BTREE_LEAF)
        {
            pucChildAddr = pucEntry + m_uiEntrySize;
            uiChildAddr = (FLMUINT)FB2UD(pucChildAddr);
        }

        // m_uiPosition automatically gets incremented.

        if (RC_BAD( rc = pNewBlk->insertEntry( pucEntry, uiChildAddr)))
        {
            RC_UNEXPECTED_ASSERT( rc);
            goto Exit;
        }
    }

    if (m_uiPosition < uiMid)
    {

        // Insert this entry now

        bInserted = TRUE;
        (void) pNewBlk->searchEntry( pucCurEntry);
        if (RC_BAD( rc = pNewBlk->insertEntry( pucCurEntry, uiCurBlkAddr)))
        {
            goto Exit;
        }
    }

    // Let caller insert into parent entry.  This rids us of recursion.

    f_memcpy( pucParentEntry, pucEntry, m_uiEntrySize);

    // Move the rest down

    pucEntry = ENTRY_POS( 0);
    pucMidEntry = ENTRY_POS( uiMid);

    entryCount( entryCount() - uiMid);
    uiMoveBytes = entryCount() * (m_uiEntrySize + m_uiEntryOvhd);
    flmAssert( uiMoveBytes < DYNSSET_BLOCK_SIZE - sizeof( FixedBlkHdr));
    f_memmove( pucEntry, pucMidEntry, uiMoveBytes);

    if( !bInserted)
    {

        // m_uiPosition -= uiMid;

        (void) searchEntry( pucCurEntry);
        if (RC_BAD( rc = insertEntry( pucCurEntry, uiCurBlkAddr)))
        {
            goto Exit;
        }
    }

    // VISIT: Could position stack to point to current element to insert.

    // Fixup the prev/next block linkages.

    if (prevBlk() != FBTREE_END)
    {
        if (RC_BAD( rc = pRoot->readBlk( prevBlk(), blkType(), &pPrevBlk )))
        {
            goto Exit;
        }

        pPrevBlk->nextBlk( pNewBlk->blkAddr());
        uiPrevBlkAddr = pPrevBlk->blkAddr();
    }
    else
    {
        uiPrevBlkAddr = FBTREE_END;
    }
    pNewBlk->prevBlk( uiPrevBlkAddr);
    pNewBlk->nextBlk( blkAddr());
    prevBlk( pNewBlk->blkAddr());

    *puiNewBlkAddr = pNewBlk->blkAddr();

Exit:

    if (pNewBlk)
    {
        pNewBlk->Release();
    }

    return( rc);
}
Пример #12
0
/****************************************************************************
Desc:	Search a single block tree.  Position for get* or for insert.
		Do a binary search on all of the entries to find a match.
		If no match then position to the entry where an insert
		will take place.
****************************************************************************/
RCODE F_BtreeBlk::searchEntry(
    void *		pvEntry,
    FLMUINT *	puiChildAddr,
    void *		pvFoundEntry)
{
    RCODE			rc = RC_SET( NE_FLM_NOT_FOUND);
    FLMUINT		uiLow;
    FLMUINT		uiMid;
    FLMUINT		uiHigh;
    FLMUINT		uiTblSize;
    FLMINT		iCompare;

    // check for zero entries.

    if (!entryCount())
    {
        uiMid = 0;
        goto Exit;
    }
    uiHigh = uiTblSize = entryCount() - 1;
    uiLow = 0;
    for(;;)
    {
        uiMid = (uiLow + uiHigh) >> 1;		// (uiLow + uiHigh) / 2

        // Use compare routine

        if (m_fnCompare)
        {
            iCompare = m_fnCompare( pvEntry, ENTRY_POS( uiMid), m_pvUserData);
        }
        else
        {
            iCompare = f_memcmp( pvEntry, ENTRY_POS( uiMid), m_uiEntrySize);
        }

        if (iCompare == 0)
        {
            if (pvFoundEntry)
            {
                f_memcpy( pvFoundEntry, ENTRY_POS( uiMid), m_uiEntrySize);
            }
            rc = NE_FLM_OK;
            goto Exit;
        }

        // Check if we are done - where wLow equals uiHigh or mid is at end.

        if (iCompare < 0)
        {
            if (uiMid == uiLow || uiLow == uiHigh)
            {
                break;
            }
            uiHigh = uiMid - 1;					// Too high
        }
        else
        {
            if (uiMid == uiHigh || uiLow == uiHigh)
            {

                // Go up one for the correct position?

                uiMid++;
                break;
            }
            uiLow = uiMid + 1;					// Too low
        }
    }

Exit:

    m_uiPosition = uiMid;
    if (puiChildAddr && blkType() != ACCESS_BTREE_LEAF)
    {
        if (uiMid == entryCount())
        {
            *puiChildAddr = lemBlk();
        }
        else
        {
            FLMBYTE *	pucChildAddr = ENTRY_POS(uiMid) + m_uiEntrySize;
            *puiChildAddr = (FLMUINT)FB2UD( pucChildAddr);
        }
    }
    return( rc);
}
bool CameraMetadata::isEmpty() const {
    return entryCount() == 0;
}
    void testSymbolVersionDefinitions()
    {
        ElfFileSet set;
        set.addFile(QStringLiteral(LIBDIR "libversioned-symbols.so"));
        QVERIFY(set.size() > 1);

        auto f = set.file(0);
        QVERIFY(f);

        const auto symDefIndex = f->indexOfSection(".gnu.version_d");
        const auto symbolVersionDefs = f->section<ElfGNUSymbolVersionDefinitionsSection>(symDefIndex);
        QVERIFY(symbolVersionDefs);
        QCOMPARE(symbolVersionDefs->entryCount(), 3u);

        ElfGNUSymbolVersionDefinition *defV1 = nullptr, *defV2 = nullptr;
        auto def = symbolVersionDefs->definition(1);
        QVERIFY(def);
        QCOMPARE(def->versionIndex(), (uint16_t)2);
        QCOMPARE(symbolVersionDefs->definitionForVersionIndex(2), def);
        if (def->auxiliarySize() == 1)
            defV1 = def;
        else
            defV2 = def;

        def = symbolVersionDefs->definition(2);
        QVERIFY(def);
        QCOMPARE(def->versionIndex(), (uint16_t)3);
        QCOMPARE(symbolVersionDefs->definitionForVersionIndex(3), def);
        if (def->auxiliarySize() == 1)
            defV1 = def;
        else
            defV2 = def;

        QVERIFY(defV1);
        QVERIFY(defV2);

        QCOMPARE(defV2->auxiliarySize(), (uint16_t)2);
        auto defEntry = defV2->auxiliaryEntry(0);
        QVERIFY(defEntry);
        QCOMPARE(defEntry->name(), "VER2");
        defEntry = defV2->auxiliaryEntry(1);
        QVERIFY(defEntry);
        QCOMPARE(defEntry->name(), "VER1");

        QCOMPARE(defV1->auxiliarySize(), (uint16_t)1);
        defEntry = defV1->auxiliaryEntry(0);
        QVERIFY(defEntry);
        QCOMPARE(defEntry->name(), "VER1");

        const auto symVerIndex = f->indexOfSection(".gnu.version");
        const auto symbolVersionTable = f->section<ElfGNUSymbolVersionTable>(symVerIndex);
        QVERIFY(symbolVersionTable);

        const auto dynTabIndex = f->indexOfSection(".dynsym");
        QVERIFY(dynTabIndex > 0);
        const auto symTab = f->section<ElfSymbolTableSection>(dynTabIndex);
        QVERIFY(symTab);
        QCOMPARE(symTab->header()->entryCount(), symbolVersionTable->header()->entryCount());

        ElfSymbolTableEntry *f1 = nullptr, *f2 = nullptr, *f_ver1 = nullptr, *f_ver2 = nullptr;
        for (uint i = 0; i < symTab->header()->entryCount(); ++i) {
            auto sym = symTab->entry(i);
            QVERIFY(sym);
            if (strcmp(sym->name(), "function1") == 0)
                f1 = sym;
            else if (strcmp(sym->name(), "function2") == 0)
                f2 = sym;
            else if (strcmp(sym->name(), "function") == 0) {
                qDebug() << symbolVersionTable->versionIndex(i);
                if (symbolVersionTable->versionIndex(i) == defV2->versionIndex())
                    f_ver2 = sym;
                else if (symbolVersionTable->versionIndex(i) == defV1->versionIndex())
                    f_ver1 = sym;
            }
        }

        QVERIFY(f1);
        QVERIFY(f2);
        QVERIFY(f_ver1);
        QVERIFY(f_ver2);
        QCOMPARE(f1->value(), f_ver1->value());
        QCOMPARE(f2->value(), f_ver2->value());
    }
Пример #15
0
/**
****************************************************************************
* Name: IccVCGTTag::Read
* 
* Purpose: Read in the tag contents into a data block
* 
* Args:
*  size - # of bytes in tag,
*  pIO - IO object to read tag from
* 
* Return: 
*  true = successful, false = failure
*****************************************************************************
*/
bool IccVCGTTag::Read(icUInt32Number size, CIccIO *pIO)
{
    qDebug() << "IccVCGTTag::Read";
    
    icTagTypeSignature sig;

    if (sizeof(icTagTypeSignature) +
        2*sizeof(icUInt32Number) +
        3*sizeof(icUInt16Number) > size)
            return false;

    if (!pIO) 
    {
        qDebug() << "if (!pIO)";
        return false;
    }

    if (!pIO->Read32(&sig))
    {
        qDebug() << "if (!pIO->Read32(&sig))";
        return false;
    }
    
    qDebug() << "sig = " << (unsigned int)sig;

    if (!pIO->Read32(&m_nReserved))
    {
        qDebug() << "if (!pIO->Read32(&m_nReserved))";
        return false;
    }
    
    qDebug() << "m_nReserved = " << (unsigned int)m_nReserved;

    icUInt32Number type;

    if (!pIO->Read32(&type))
    {
        qDebug() << "if (!pIO->Read32(&type))";
        return false;
    }

    qDebug() << "type =" << (int)type;
    
    if(type==cmVideoCardGammaTableType)
    {
        //sizes
        icUInt16Number ch, ec, esz;
        if (!pIO->Read16(&ch))
            return false;

        if (!pIO->Read16(&ec))
            return false;

        if (!pIO->Read16(&esz))
            return false;



        SetSize(ch, ec);

        if (curves_)
            free(curves_);
        curves_ = (icUInt16Number*)malloc(channels_*entryCount_*sizeof(icUInt16Number));
        if(esz == sizeof(icUInt16Number))
        {
            if (pIO->Read16(curves_, channels_*entryCount_)!=(icInt32Number)(channels_*entryCount_))
                return false;
        }
        else
        {
            icInt8Number t;
            const unsigned long ONE_COEF_16 = 1<<16;
            const unsigned long ONE_COEF_esz = 1<<(8*esz);
            for(unsigned i=0;i<channels();++i)
                for(unsigned j=0;j<entryCount();++j)
                {
                    unsigned long long v = 0;
                    for(unsigned k=0;k<esz;++k)
                    {
                        if (pIO->Read8(&t, 1)!=1)
                            return false;
                        v = v*2 + t;
                    }
                    curves_[i*entryCount_+j] = icUInt16Number((long double)(v)/(ONE_COEF_esz-1)*(ONE_COEF_16-1));
                }

        }
    }
    else if (type == cmVideoCardGammaFormulaType)
    {
        SetSize(3, 256);
        
        double vcgt[3][3]; // red gamma, red min, red max; green ...; blue ...
        const unsigned long ONE_COEF = 1<<16;
        for (unsigned ch = 0; ch < 3; ch++)
            for (unsigned i = 0; i < 3; i++)
            {
                unsigned long value;
                if (!pIO->Read32(&value))
                {
                    qDebug() << "if (!pIO->Read32(&value))" << ch << i;
                    return false;
                }
                
                vcgt[ch][i] = value / static_cast<double>(ONE_COEF);
            }
        
        if (curves_)
            free(curves_);
        curves_ = (icUInt16Number*)malloc(channels_*entryCount_*sizeof(icUInt16Number));
        
        for (int ch=0;ch<3;ch++)
        {
            if (vcgt[ch][0] < 0.1 || vcgt[ch][0] > 10.0)
            {
                qDebug() << "vcgt gamma incorrect value:" << vcgt[ch][0] << "channel:" << ch;
                return false;
            }
            
            double range = vcgt[ch][2] - vcgt[ch][1];
            if (range <= 0.0)
            {
                qDebug() << "vcgt incorrect min/max values:" << vcgt[ch][1] << vcgt[ch][2];
            }
            
            for (int i = 0; i < entryCount_; i++)
            {
                double y = vcgt[ch][1] + range * std::pow(i/255.0, vcgt[ch][0]);
                y = std::min(y, 1.0);
                curves_[ch*entryCount_ + i] = static_cast<icUInt16Number>(y*(ONE_COEF - 1) );
            }
        }
    }
    else
    {
        qDebug() << "Unknown VCGT type" << type;
        return false;
    }
    
    return true;
}