void MemoryTablePrivate::updateValue(const value_type &value, quint32 valueSize, quint32 offset, TableMetadata *table) { Allocation *allocation = allocationAt(offset, table); Q_ASSERT(allocation->size >= requiredSpace(valueSize)); allocation->dataSize = valueSize; insertData(allocation->data, allocation->dataSize, value); }
quint32 MemoryTablePrivate::allocate(quint32 size, TableMetadata *table, bool indexRequired) { const quint32 availableSpace = freeSpace(table); if (indexRequired) { // Even if satisfied from the free list, this allocation requires there to be space for expanded index if (availableSpace < sizeof(IndexElement)) { return 0; } } // Align the allocation so that the header is directly accessible quint32 allocationSize = static_cast<quint32>(requiredSpace(size)); allocationSize = roundUp(allocationSize, sizeof(quint32)); if (table->freeList) { // Try to reuse a freed block quint32 *bestOffset = 0; Allocation *bestBlock = 0; quint32 *freeOffset = &table->freeList; while (*freeOffset) { Allocation *freeBlock = allocationAt(*freeOffset, table); if (freeBlock->size >= allocationSize) { // This block is large enough if (!bestBlock || bestBlock->size > freeBlock->size) { // It's our best fit so far bestBlock = freeBlock; bestOffset = freeOffset; } } freeOffset = &freeBlock->nextOffset; } if (bestOffset) { // TODO: if this block is too large, should it be partitioned? quint32 rv = *bestOffset; *bestOffset = bestBlock->nextOffset; return rv; } } // Is there enough space for this allocation? if (availableSpace < (allocationSize + (indexRequired ? sizeof(IndexElement) : 0))) { return 0; } // Allocate the space immediately below the already-allocated space table->freeOffset -= allocationSize; Allocation *allocation = allocationAt(table->freeOffset, table); allocation->size = allocationSize; return table->freeOffset; }
MemoryTablePrivate::Error MemoryTablePrivate::insert(const key_type &key, const value_type &value, TableMetadata *table) { const quint32 valueSize = dataSize(value); IndexElement *tableEnd = end(table); IndexElement *position = std::lower_bound(begin(table), tableEnd, key); if (position != tableEnd && position->key == key) { // This is a replacement - the item has an allocation already Allocation *allocation = allocationAt(position->offset, table); if (allocation->size < requiredSpace(valueSize)) { // Replace the existing allocation with a bigger one quint32 newOffset = allocate(valueSize, table, false); if (!newOffset) return MemoryTable::InsufficientSpace; deallocate(position->offset, table); position->offset = newOffset; } else { // Reuse this allocation // TODO: swap with a better fit from the free list? } } else { // This item needs to be added to the index if (table->count == std::numeric_limits<quint32>::max()) return MemoryTable::InsufficientSpace; quint32 offset = allocate(valueSize, table, true); if (!offset) return MemoryTable::InsufficientSpace; // For index insertion, move the displaced elements of the index if (position != tableEnd) std::memmove(position + 1, position, (tableEnd - position) * sizeof(IndexElement)); ++(table->count); position->key = key; position->offset = offset; } Q_ASSERT(contains(key, table)); // Ensure that the data allocation does not overlap the index space Q_ASSERT((reinterpret_cast<char *>(table) + table->freeOffset) >= reinterpret_cast<char *>(end(table))); // Update the value stored at the position updateValue(value, valueSize, position->offset, table); return MemoryTable::NoError; }
VRectanglef VArabicSupport_cl::GetCharacterDimension( wchar_t wcChar, VisFont_cl * pFont ) { VASSERT_MSG(pFont!=NULL, "Specified font is NULL"); VRectanglef requiredSpace(0,0,0,0); // Convert to UTF8 const wchar_t singleCharacter[2] = {wcChar, 0}; char utf8Representation[8]; int iSize = VString::ConvertWCharToUTF8String(singleCharacter, 1, NULL, 0); VString::ConvertWCharToUTF8String(singleCharacter, 1, utf8Representation, iSize); utf8Representation[iSize] = '\0'; //check if the end-representation is present if(pFont!=NULL) pFont->GetTextDimension(utf8Representation,requiredSpace,1); return requiredSpace; }